]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge with ../linux-2.6
authorTony Lindgren <tony@atomide.com>
Thu, 10 Nov 2005 01:24:02 +0000 (17:24 -0800)
committerTony Lindgren <tony@atomide.com>
Thu, 10 Nov 2005 01:24:02 +0000 (17:24 -0800)
244 files changed:
Documentation/arm/OMAP/README [new file with mode: 0644]
Makefile
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/.gitignore [new file with mode: 0644]
arch/arm/boot/compressed/.gitignore [new file with mode: 0644]
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head-omap.S [new file with mode: 0644]
arch/arm/boot/compressed/head.S
arch/arm/configs/omap_generic_1510_defconfig [new file with mode: 0644]
arch/arm/configs/omap_generic_1610_defconfig [new file with mode: 0644]
arch/arm/configs/omap_generic_1710_defconfig [new file with mode: 0644]
arch/arm/configs/omap_generic_2420_defconfig [new file with mode: 0644]
arch/arm/configs/omap_h2_1610_defconfig
arch/arm/configs/omap_h3_1710_defconfig [new file with mode: 0644]
arch/arm/configs/omap_h4_2420_defconfig [new file with mode: 0644]
arch/arm/configs/omap_innovator_1510_defconfig [new file with mode: 0644]
arch/arm/configs/omap_innovator_1610_defconfig [new file with mode: 0644]
arch/arm/configs/omap_osk_5912_defconfig [new file with mode: 0644]
arch/arm/configs/omap_perseus2_730_defconfig [new file with mode: 0644]
arch/arm/configs/palmte_defconfig [new file with mode: 0644]
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/board-generic.c
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-innovator.c
arch/arm/mach-omap1/board-netstar.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap1/board-palmte.c [new file with mode: 0644]
arch/arm/mach-omap1/board-perseus2.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap1/clock.c [new file with mode: 0644]
arch/arm/mach-omap1/clock.h [new file with mode: 0644]
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/id.c
arch/arm/mach-omap1/io.c
arch/arm/mach-omap1/irq.c
arch/arm/mach-omap1/leds-h2p2-debug.c
arch/arm/mach-omap1/leds.c
arch/arm/mach-omap1/mux.c [new file with mode: 0644]
arch/arm/mach-omap1/serial.c
arch/arm/mach-omap1/time.c
arch/arm/mach-omap2/Kconfig [new file with mode: 0644]
arch/arm/mach-omap2/Makefile [new file with mode: 0644]
arch/arm/mach-omap2/Makefile.boot [new file with mode: 0644]
arch/arm/mach-omap2/board-generic.c [new file with mode: 0644]
arch/arm/mach-omap2/board-h4.c [new file with mode: 0644]
arch/arm/mach-omap2/clock.c [new file with mode: 0644]
arch/arm/mach-omap2/clock.h [new file with mode: 0644]
arch/arm/mach-omap2/devices.c [new file with mode: 0644]
arch/arm/mach-omap2/id.c [new file with mode: 0644]
arch/arm/mach-omap2/io.c [new file with mode: 0644]
arch/arm/mach-omap2/irq.c [new file with mode: 0644]
arch/arm/mach-omap2/mux.c [new file with mode: 0644]
arch/arm/mach-omap2/prcm.h [new file with mode: 0644]
arch/arm/mach-omap2/serial.c [new file with mode: 0644]
arch/arm/mach-omap2/sram-fn.S [new file with mode: 0644]
arch/arm/mach-omap2/timer-gp.c [new file with mode: 0644]
arch/arm/mm/Kconfig
arch/arm/mm/Makefile
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/bootreason.c [new file with mode: 0644]
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/clock.h [deleted file]
arch/arm/plat-omap/common.c
arch/arm/plat-omap/common.h [new file with mode: 0644]
arch/arm/plat-omap/devices.c [new file with mode: 0644]
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dsp/Kconfig [new file with mode: 0644]
arch/arm/plat-omap/dsp/Makefile [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp_common.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp_common.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp_core.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp_ctl.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp_ctl_core.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp_mem.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/error.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/fifo.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/hardware_dsp.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/ipbuf.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/ipbuf.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/mblog.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/proclist.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/task.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/taskwatch.c [new file with mode: 0644]
arch/arm/plat-omap/dsp/uaccess_dsp.S [new file with mode: 0644]
arch/arm/plat-omap/dsp/uaccess_dsp.h [new file with mode: 0644]
arch/arm/plat-omap/gpio-switch.c [new file with mode: 0644]
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/mux.c
arch/arm/plat-omap/pm.c
arch/arm/plat-omap/sleep.S
arch/arm/plat-omap/sram.c
arch/arm/plat-omap/sram.h [deleted file]
arch/arm/plat-omap/usb.c
drivers/Kconfig
drivers/Makefile
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/omap-rng.c [new file with mode: 0644]
drivers/char/omap-rtc.c [new file with mode: 0644]
drivers/char/omap-rtc.h [new file with mode: 0644]
drivers/char/watchdog/Kconfig
drivers/char/watchdog/Makefile
drivers/char/watchdog/omap_wdt.c [new file with mode: 0644]
drivers/char/watchdog/omap_wdt.h [new file with mode: 0644]
drivers/i2c/Kconfig
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-omap.c [new file with mode: 0644]
drivers/i2c/busses/i2c-omap.h [new file with mode: 0644]
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/gpio_expander_omap.c [new file with mode: 0644]
drivers/i2c/chips/isp1301_omap.c
drivers/i2c/chips/menelaus.c [new file with mode: 0644]
drivers/i2c/chips/tlv320aic23.c [new file with mode: 0644]
drivers/i2c/chips/tps65010.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/innovator_ps2.c [new file with mode: 0644]
drivers/input/keyboard/omap-keypad.c [new file with mode: 0644]
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/omap/Makefile [new file with mode: 0644]
drivers/input/touchscreen/omap/ads7846.h [new file with mode: 0644]
drivers/input/touchscreen/omap/omap_ts.c [new file with mode: 0644]
drivers/input/touchscreen/omap/omap_ts.h [new file with mode: 0644]
drivers/input/touchscreen/omap/ts_hx.c [new file with mode: 0644]
drivers/input/touchscreen/omap/ts_inn1510.c [new file with mode: 0644]
drivers/input/touchscreen/omap/ts_osk.c [new file with mode: 0644]
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/omap/Makefile [new file with mode: 0644]
drivers/media/video/omap/camera_core.c [new file with mode: 0644]
drivers/media/video/omap/camera_core.h [new file with mode: 0644]
drivers/media/video/omap/camera_hw_if.h [new file with mode: 0644]
drivers/media/video/omap/omap16xxcam.c [new file with mode: 0644]
drivers/media/video/omap/omap16xxcam.h [new file with mode: 0644]
drivers/media/video/omap/ov9640.h [new file with mode: 0644]
drivers/media/video/omap/sensor_if.h [new file with mode: 0644]
drivers/media/video/omap/sensor_ov9640.c [new file with mode: 0644]
drivers/mmc/Kconfig
drivers/mmc/Makefile
drivers/mmc/mmc.c
drivers/mmc/mmc_block.c
drivers/mmc/omap.c [new file with mode: 0644]
drivers/mmc/omap.h [new file with mode: 0644]
drivers/mtd/maps/omap_nor.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/omap-hw.c [new file with mode: 0644]
drivers/mtd/nand/omap-nand-flash.c [new file with mode: 0644]
drivers/net/irda/Kconfig
drivers/net/irda/Makefile
drivers/net/irda/omap1610-ir.c [new file with mode: 0644]
drivers/net/smc91x.c
drivers/net/smc91x.h
drivers/pcmcia/omap_cf.c
drivers/serial/8250.c
drivers/ssi/Kconfig [new file with mode: 0644]
drivers/ssi/Makefile [new file with mode: 0644]
drivers/ssi/omap-tsc2101.c [new file with mode: 0644]
drivers/ssi/omap-tsc2101.h [new file with mode: 0644]
drivers/ssi/omap-uwire.c [new file with mode: 0644]
drivers/ssi/omap-uwire.h [new file with mode: 0644]
drivers/usb/gadget/Kconfig
drivers/usb/gadget/omap_udc.c
drivers/usb/host/ohci-omap.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/omap/Kconfig [new file with mode: 0644]
drivers/video/omap/Makefile [new file with mode: 0644]
drivers/video/omap/debug.h [new file with mode: 0644]
drivers/video/omap/dispc.c [new file with mode: 0644]
drivers/video/omap/dispc.h [new file with mode: 0644]
drivers/video/omap/lcd_h2.c [new file with mode: 0644]
drivers/video/omap/lcd_h3.c [new file with mode: 0644]
drivers/video/omap/lcd_h4.c [new file with mode: 0644]
drivers/video/omap/lcd_inn1510.c [new file with mode: 0644]
drivers/video/omap/lcd_inn1610.c [new file with mode: 0644]
drivers/video/omap/lcd_osk.c [new file with mode: 0644]
drivers/video/omap/lcd_p2.c [new file with mode: 0644]
drivers/video/omap/lcd_palmte.c [new file with mode: 0644]
drivers/video/omap/lcdc.c [new file with mode: 0644]
drivers/video/omap/omapfb_main.c [new file with mode: 0644]
drivers/video/omap/rfbi.c [new file with mode: 0644]
drivers/video/omap/sossi.c [new file with mode: 0644]
drivers/video/omap/sossi.h [new file with mode: 0644]
include/asm-arm/.gitignore [new file with mode: 0644]
include/asm-arm/arch-omap/board-h4.h
include/asm-arm/arch-omap/board-innovator.h
include/asm-arm/arch-omap/camera.h [new file with mode: 0644]
include/asm-arm/arch-omap/clock.h [new file with mode: 0644]
include/asm-arm/arch-omap/common.h
include/asm-arm/arch-omap/cpu.h
include/asm-arm/arch-omap/dma.h
include/asm-arm/arch-omap/entry-macro.S
include/asm-arm/arch-omap/fpga.h
include/asm-arm/arch-omap/gpio.h
include/asm-arm/arch-omap/gpioexpander.h [new file with mode: 0644]
include/asm-arm/arch-omap/hardware.h
include/asm-arm/arch-omap/io.h
include/asm-arm/arch-omap/irqs.h
include/asm-arm/arch-omap/memory.h
include/asm-arm/arch-omap/menelaus.h [new file with mode: 0644]
include/asm-arm/arch-omap/mux.h
include/asm-arm/arch-omap/omap1510.h
include/asm-arm/arch-omap/omap24xx.h
include/asm-arm/arch-omap/omapfb.h [new file with mode: 0644]
include/asm-arm/arch-omap/pm.h
include/asm-arm/arch-omap/prcm.h [new file with mode: 0644]
include/asm-arm/arch-omap/sram.h [new file with mode: 0644]
include/asm-arm/arch-omap/system.h
include/asm-arm/arch-omap/timex.h
include/asm-arm/arch-omap/uncompress.h
include/asm-arm/dma-mapping.h
include/asm-arm/hardware/clock.h
include/asm-arm/hardware/tsc2101.h [new file with mode: 0644]
include/asm-arm/setup.h
include/linux/fb.h
include/linux/input.h
init/do_mounts.c
kernel/printk.c
sound/arm/Kconfig
sound/arm/Makefile
sound/arm/omap-aic23.c [new file with mode: 0644]
sound/arm/omap-aic23.h [new file with mode: 0644]
sound/arm/omap-alsa-dma.c [new file with mode: 0644]
sound/arm/omap-alsa-dma.h [new file with mode: 0644]
sound/arm/omap-alsa-mixer.c [new file with mode: 0644]
sound/oss/Kconfig
sound/oss/Makefile
sound/oss/omap-audio-aic23.c [new file with mode: 0644]
sound/oss/omap-audio-dma-intfc.c [new file with mode: 0644]
sound/oss/omap-audio-dma-intfc.h [new file with mode: 0644]
sound/oss/omap-audio-tsc2101.c [new file with mode: 0644]
sound/oss/omap-audio.c [new file with mode: 0644]
sound/oss/omap-audio.h [new file with mode: 0644]

diff --git a/Documentation/arm/OMAP/README b/Documentation/arm/OMAP/README
new file mode 100644 (file)
index 0000000..e002e32
--- /dev/null
@@ -0,0 +1,436 @@
+
+                  README for ARM based OMAP processor from TI
+                  ===========================================
+
+This is the README for Linux 2.6 on ARM based TI OMAP processors.
+
+In the first section it gives some general hints how to start with OMAP Linux.
+When successfully build a OMAP Linux kernel with help of first section and no 
+bootloader is already on the board, section 2 gives some tips how to use
+commercial JTAG tools. 
+
+In March 2004 the Linux Kernel 2.6 for ARM based TI OMAP processors was cleaned.
+The goal was to send clean patches to RMK's official ARM tree and to make it 
+easier to add new OMAP processors or boards to the kernel tree. To keep the
+kernel tree clean now, this document describes also some steps how 
+to add code for a new OMAP processor or OMAP based board to the OMAP Linux 2.6 
+kernel tree. This is what the third section of this document is about.
+
+Section 4 of this README reports some rules to be followed to write 
+clean code to make it ready for easy inclusion into public OMAP Linux kernel.
+
+For more information also see TI's 'Linux Community for Texas Instruments OMAP
+Processors' web page:
+
+http://linux.omap.com
+
+There, various downloads and resources can be found (e.g. documentation how
+to build the kernel, how to use u-boot with OMAP Linux, pre-built tool chain
+etc.).
+
+The mailing list for OMAP Linux is hosted there, too:
+
+http://linux.omap.com/mailman/listinfo
+
+
+1. General hints how to start with OMAP Linux
+--------------------------------------------------------------
+
+The minimal setup is a arm-linux-gcc cross compiler, make, and some editor.
+You will also most likely need a JTAG to flash the bootloader for the first
+time.
+
+The first step is to get a bootloader for your board, u-boot is the
+recommended one:
+
+http://sourceforge.net/projects/uboot/
+
+Then you need to compile it with the same cross compiler as you would use
+for the Linux kernel. Then you need to flash it to the board either via the
+serial port, or by using a JTAG.
+
+Once you have the bootloader running, you can compile the kernel.
+
+You can get the OMAP sources either from the BitKeeper tree, or by
+applying patches. The BitKeeper tree has the most up to date sources
+and is the recommended one.
+
+- Using BitKeeper:
+You need to download the bk tool from:
+
+http://www.bitmover.com/
+
+Download the dynamic one (x86-glibc22-linux) instead of the static 
+(x86-static-linux). Some users reported problems with the static version.
+
+After bk tool is installed, to learn more about bitkeeper you can follow the
+tutorial at:
+
+http://www.bitkeeper.com/UG/
+
+Then you can clone OMAP Linux by:
+
+bk clone http://linux-omap.bkbits.net/main
+
+Now, you have a copy (clone) of the reprository. To work with it and to
+compile the kernel you have to check out the files from your local 
+repository by:
+
+bk -r get (or: bk -r edit)
+
+For kernel related BitKeeper information see also kernel documentation in:
+
+Documentation/BK-usage/bk-kernel-howto.txt
+
+Hint: If you are sitting behind a firewall and have to use a proxy for 
+internet access, you can access BitKeeper by http by setting the 
+http_proxy envirionment variable:
+
+http_proxy=http://proxy_username:proxy_password@proxy_name:proxy_port/
+
+If you use bash shell, then this might look like:
+
+export http_proxy=http://foo:123@abc.host.com:8080/
+
+with:
+
+foo: Your user name for the proxy
+123: Your password for the proxy
+abc.host.com: The name of your proxy you use for internet access
+8080: The port used on to access the proxy
+
+
+- Using Patches:
+
+If you don't want to use BitKeeper, then you can do the same thing with patch.
+
+Download the latest OMAP Linux patch from:
+
+http://www.muru.com/linux/omap/
+
+Get a matching Linux kernel from:
+
+ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
+
+For example, if you download Linux-2.6.4-omap1 from muru.com, then you need
+linux-2.6.4 kernel from kernel.org:
+
+$ wget ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.4.tar.bz2
+$ tar xjf linux-2.6.4.tar.bz2
+$ cd linux-2.6.4
+$ cat ../Linux-2.6.4-omap1 | patch -p1
+
+Note: If OMAP patch from muru.com is against a kernel release candidate, 
+marked by -rcX, then kernel can be found on kernel.org under v2.6/testing/
+
+Now, if you have a local kernel tree, either by BitKeeper or by patch, you 
+should look into arch/arm/config/ to see which of the various omap_xxx
+configurations there you want to use. For example, if you have a OMAP1510
+based Innovator board, you select omap_innovator_1510_defconfig by 
+
+$ make omap_innovator_1510_defconfig
+
+at top level directory (linux-2.6.4 in the example above).
+
+Then you can compile the kernel with
+
+$ make vmlinux
+
+Or make Image or make zImage or make uImage.
+
+Once you have the kernel compiled, you can upload it to the board via serial
+port or JTAG (see below).
+
+Then you need a root file system either as initrd or on the flash.
+
+Once you have the system booting to Linux, you can use pretty much any Linux
+applications cross compiled for ARM.
+
+
+2. JTAG usage
+--------------------------------------------------------------
+
+If the flash of your board is really 'empty' and no bootloader is on the board
+(e.g. u-boot) then you need a JTAG connection. With JTAG you can write
+a bootloader to board's flash or download OMAP Linux kernel. For OMAP
+commercial JTAG tools are available, so you have to pay for it.
+
+Examples are TI's Code Composer Studio (CCS) or Lauterbach's TRACE32 JTAG.
+
+- Linux kernel download with CCS
+
+You can use CCS to directly load an ELF file to your board. For example, use  
+arch/arm/boot/compressed/vmlinux. zImage isn't suited because it is not an ELF
+file. CCS looks for .out files, so copy arch/arm/boot/compressed/vmlinux 
+to vmlinux.out and load it using CCS. Or use the filter *.* to select
+vmlinux directly. Remember to run arm-linux-strip on ELF file first as CCS 
+get stroppy about unstripped ELF files.
+
+If you want vmlinux to be linked to run at a specific address, you can use 
+the CONFIG_ZBOOT options in the kernel build. But first try without
+CONFIG_ZBOOT as the compressed image should be able to run from address
+zero (if your CCS .gel files map address zero.)
+
+Otherwise, use something like this:
+
+CONFIG_ZBOOT_ROM=y
+CONFIG_ZBOOT_ROM_TEXT=10408000
+CONFIG_ZBOOT_ROM_BSS=10800000
+
+Also note that CCS is pretty useless for debugging Linux as it doesn't
+properly handle virtual memory. In other words, once the MMU is
+turned on and Linux is using virtual memory, CCS can no longer
+properly disassemble, set breakpoints or read memory.
+
+
+- Linux kernel download with Lauterbach TRACE32
+
+To be done.
+
+
+3. How to add new processor or board to OMAP Linux kernel tree
+--------------------------------------------------------------
+
+It is assumed that the OMAP processor to be added is based on an already 
+supported ARM core (e.g. ARM925 or ARM926). How to add support for new ARM 
+processor core that is not supported by ARM Linux is not scope of this document.
+
+1. If a new OMAP processor should be added, identify the ARM core of this 
+processor. E.g. at time of writing this document in March 2004 OMAP730 (ARM926 
+core), OMAP1510 (ARM925 core) and OMAP1610 (ARM926 core) are supported.
+
+For a new board or device, identify the OMAP processor on the board. E.g. at 
+time of writing this document in March 2004 four boards are supported: 
+Innovator1510 (OMAP1510 processor), Innovator1610 (OMAP1610 processor), 
+Perseus2 (OMAP730 processor) and H2 (OMAP1610 processor).
+
+/* Discussion needed: How to handle the tons of compatible processors? 
+E.g. what to do if OMAP16xx is mainly identical with OMAP16yy? */
+
+2. Start with arch/arm/mach-omap/Kconfig and add a new processor or board 
+option.
+
+To add a new processor add a new config option to the "OMAP Core Type" choice. 
+See examples for the syntax. The config option has to be called "ARCH_OMAPxxxx" 
+where xxxx is the number of OMAP processor. Don't forget to select a existing
+clock frequency or to add a new one in "OMAP Feature Selections" section for
+your new processor. 
+
+To add a new board or device, add a new config option to the "OMAP Board Type" 
+choice. See examples for the syntax. The config option for boards has to be 
+called "MACH_OMAP_yyyy" where yyyy is the board name. Don't forget to add a 
+short help.
+
+Note: Kernel 2.6 Kconfig system will automatically expand the configuration 
+names with a leading "CONFIG_". So "ARCH_OMAPxxxx" will be expanded to 
+"CONFIG_ARCH_OMAPxxxx" and "MACH_OMAP_yyy" will expand to 
+"CONFIG_MACH_OMAP_yyyy". In code this can then be used by macros like 
+"#ifdef CONFIG_ARCH_OMAPxxxx" and "#ifdef CONFIG_MACH_OMAP_yyyy".
+
+Note: How to handle boards which are compatible or extensions of other boards? 
+See MACH_OMAP_H2 for example. The H2 depends on MACH_OMAP_INNOVATOR and expands 
+it. This is done by an additional select MACH_OMAP_INNOVATOR in MACH_OMAP_H2
+configuration option. With this the whole MACH_OMAP_INNOVATOR configuration is
+selected and an additional symbol CONFIG_MACH_OMAP_H2 is available to
+distinguish between INNOVATOR and H2 where necessary. 
+
+3a. Only for new processors: Add the ARCH_OMAPxxxx to the correct ARM core in 
+arch/arm/mm/Kconfig. E.g. ARCH_OMAP730 in CPU_ARM926T configuration.
+
+3b. Only for new boards: Register the board within ARM Linux machine 
+registration system from RMK. For the CONFIG_ section use the same name like 
+in arch/arm/mach-omap/Kconfig. E.g. MACH_OMAP_yyyy. For MACH_TYPE_ section use 
+OMAP_yyyy where yyyy is the board name like above.
+
+Note: The elements of RMKs machine registration are used in 
+arch/arm/tools/mach-types. While kernel compilation
+include/asm-arm/mach-types.h is generated automagically from this file. The
+content of mach-types.h then is used for machine identification by kernel
+bootcode and can be used for board identification.
+
+Note: The ARM Linux machine registration system from RMK can be found under:
+
+www.arm.linux.org.uk/developer/machines/
+
+Note: Only OMAP based boards should be registered to RMKs registration
+system. Not processors.
+
+4. Add a processor or board specific header file in include/asm-arm/arch-omap/. 
+Use board-yyyy.h with yyyy board name or omapxxxx.h with xxxx processor number.
+
+5. Add a processor or board specific section into include/asm-arm/arch-omap/
+hardware.h. Use examples for syntax and use CONFIG_ names as defined in 
+arch/arm/mach-omap/Kconfig.
+
+6. Add processor or board specific macros to board-yyyy.h or omapxxxx.h. The
+macros to these specific files have to be named OMAPxxxx_ with xxxx processor
+number to make them unique.
+
+7a. Only for new boards: Add a file board-yyyy.c with yyyy board name to 
+arch/arm/mach-omap/. Put board specific initialization code and resource 
+description into this file. The first element of MACHINE_START must be equal to 
+MACH_TYPE_ section of machine registration (see arch/arm/tools/mach-types after 
+machine registration at RMKs registration system).
+
+Put only code into this file that is board specific and not common. See other 
+board files for examples.
+
+7b. Only for new processors: Add processor specific IO description and
+iotable_init() to arch/arm/mach-omap/common.c. See examples for the syntax.
+
+If you have introduced new clock definition in 2., add support for this new
+clock in include/asm-arm/arch-omap/clocks.h and arch/arm/mach-omap/clocks.c.
+
+8. Only for new boards: Add "obj-$(CONFIG_MACH_OMAP_yyyy) += board-yyyy.o" with 
+yyyy board name to arch/arm/mach-omap/Makefile. This is used to compile your new
+board specific initialization code from 7a.
+
+9. Check if other of the existing files have to be adjusted for the new 
+processor or board. Things to check:
+
+- Pin multiplexing
+- GPIO configuration
+- Powermanagement
+- Clocking
+- Interrupt controller and interrupt configuration
+- Additional board specific things (e.g. FPGAs)
+
+If other existing files or device drivers have to be changed, use the following 
+mechanism for processor specific things:
+
+#ifdef CONFIG_ARCH_OMAPxxxx
+       if (cpu_is_omapxxxx()) {
+               /* Do the OMAPxxxx processor specific magic */
+       }
+#endif
+
+Note: cpu_is_omapxxxx() macro is defined in include/asm-arm/arch-omap/hardware.h
+and uses OMAP_ID_REG for runtime processor identifcation.
+
+For board differentiation use board macro from include/asm-arm/mach-types.h:
+
+#ifdef CONFIG_MACH_OMAP_yyyy
+       if (machine_is_omap_yyyy()) {
+               /* Do the board specific magic */
+       }
+#endif
+
+Note: If technically possible and already implemented the OMAP Linux kernel
+has support for a "one binary fits all" machanism. That is, the goal is to be
+able to enable support for multiple OMAP processors and/or boards in Kconfig
+system. Then it is decided by bootparameters and at runtime on which processor 
+and/or board the kernel is actually running on. With this machanism it is 
+possible to use the same kernel binary on different OMAP processors or boards 
+without recompiling. This is achived by the cpu_is_omapxxxx() and
+machine_is_omap_yyyy() macros.
+
+On the other hand, for memory limited embedded systems it should be possible
+to compile the kernel with support for only one processor/board combination.
+For this a kernel binary is necessary which isn't bloated with code for all
+other (unused) processors and boards. This is achived by using the preprocessor
+CONFIG_ARCH_OMAPxxxx and CONFIG_MACH_OMAP_yyyy macros around the runtime
+cpu_is_omapxxxx() and machine_is_omap_yyyy() selection.
+
+At the moment, the price for this flexibility is a increased number of #ifdef's
+throughout the code.
+
+10. Configure the kernel by make menuconfig or make xconfig and select the new 
+processor or board.
+
+11. Compile the kernel by an appropriate cross compilation toolchain. Make this
+until the code compiles error and warning free. The kernel should also be 
+compiled with the various debug checking thingies enabled (e.g.
+CONFIG_DEBUG_SPINLOCK,  CONFIG_DEBUG_PAGEALLOC etc.).
+
+/* ToDo: Anything to say about toolchain? */
+
+12. Download the kernel image to the board and test it until it works ;-)
+
+It's not in the scope of this document how to do this (use a appropriate 
+bootloader or JTAG download).
+
+Note: The kernel initialization code expects some special values in the
+registers R0, R1 and R2 of the ARM processor. These registers have to be
+written by bootloader or debugger before starting the kernel. R0 has to be
+zero, R1 has to contain the machine number from machine registration in
+arch/arm/tools/mach-types. R2 points to the physical address of tagged list
+in system RAM. For more information see Documentation/arm/Booting.
+
+While testing a new processor or board configuration, it is recommended to 
+enable low level debugging. This uses low level output functions to print kernel
+messages on serial line before console is working. Enable it by 
+
+Kernel hacking -> Kernel debugging -> Kernel low-level debugging functions
+
+in kernel configuration system.
+
+13. Check that no other processors or boards are broken by the new code. A first
+test is to successful compile the other omap_xxx configurations from 
+arch/arm/configs/. Do this by e.g.
+
+cd linux
+make omap_innovator_1510_defconfig
+Compile the kernel
+
+Even better: Enable support for several processors and boards in Kconfig
+system and compile kernel successfully.
+
+14. Only for new boards: Add a new default board configuration to 
+arch/arm/configs. Use omap_yyyy_xxxx_defconfig with yyyy boardname and xxxx 
+processornumber as filename.
+
+15. If the new code works, compiles without warnings and seems to break no other
+configurations, post a patch to linux-omap-open-source@list.ti.com.
+
+With sending a patch to the community, it is reviewed, can be used and tested by
+other users. It then can be included into the public OMAP kernel tree. 
+
+16. Then adapt device drivers or write additional drivers for non-existing 
+processor peripherals or board devices. Improve and maintain the code for your 
+new processor or board.
+
+
+4. General guidelines to write clean and OMAP Linux compatible code
+-------------------------------------------------------------------
+
+- For register access use the __REG8/16/32() macros. At the moment, see first
+example in include/asm-arm/arch-omap/hardware.h.
+
+Allegedly __REG() makes at least some versions of GCC emit tighter code
+than the more direct wrappers. Presumably by making it easier to use certain 
+addressing modes. 
+
+Make sure that the registers names are clearly marked as being registers
+(and not addresses of registers). This has to be done by adding a '_REG'
+suffix. E.g.
+
+#define OMAP_ID_REG  (__REG32(0xfffed400))
+#define DPLL_CTL_REG (__REG16(0xfffecf00))
+
+__raw_read[bwl] and __raw_write[bwl] are deprecated. They will converted to
+__REG8/16/32() syntax, soon. Don't use anything else like own pointer
+definitions or in[bwl]/out[bwl] etc., too.
+
+- Make read-modify-write register access preemption save. Use spin_lock() and 
+spin_unlock() where necessary. If an IRQ handler can access the registers, 
+use spin_lock_irqsave(), too. 
+
+- Functions declared as __init shouldn't have any references after the kernel 
+initialization phase is complete. Usually they should be static as well.
+
+- Don't use return statements at end of void functions.
+
+- Use consistent indentation style. Don't use space indentations. Use tab 
+indentations.
+
+- In general use Linux formatting style. See Documentation/CodingStyle for more
+information. If you use GNU emacs, see also chapter 8 of that document how to
+add a linux-c-mode to emacs.
+
+
+------------------------------------------------------------------
+Last modified 13. June 2004
+The OMAP Linux Kernel Team
+Dirk Behme <dirk.behme@de.bosch.com>
index ea96da1572d595de19daeda44b2364416e9bd3a0..4a5e786edc188eb6f9ca242075c2420376ad51ec 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,9 @@ NAME=Affluent Albatross
 # Comments in this file are targeted only to the developer, do not
 # expect to learn how to build the kernel reading this file.
 
+# Add custom flags here to avoid conflict with updates
+EXTRAVERSION := $(EXTRAVERSION)-omap2
+
 # Do not print "Entering directory ..."
 MAKEFLAGS += --no-print-directory
 
@@ -169,6 +172,7 @@ KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
 SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                                  -e s/s390x/s390/ -e s/parisc64/parisc/ )
+SUBARCH := arm
 
 # Cross compiling and selecting different set of gcc/bin-utils
 # ---------------------------------------------------------------------------
@@ -190,7 +194,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
 
 ARCH           ?= $(SUBARCH)
-CROSS_COMPILE  ?=
+CROSS_COMPILE  ?= arm-linux-
 
 # Architecture as present in compile.h
 UTS_MACHINE := $(ARCH)
index ec77721507cb746c238afe4d4ed56a62b97f4b38..bd66f81c9365431285a03d29d95fcb4946310cba 100644 (file)
@@ -239,6 +239,8 @@ source "arch/arm/plat-omap/Kconfig"
 
 source "arch/arm/mach-omap1/Kconfig"
 
+source "arch/arm/mach-omap2/Kconfig"
+
 source "arch/arm/mach-s3c2410/Kconfig"
 
 source "arch/arm/mach-lh7a40x/Kconfig"
@@ -429,8 +431,7 @@ config LEDS
          system, but the driver will do nothing.
 
 config LEDS_TIMER
-       bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
-                           MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
+       bool "Timer LED" if !ARCH_CDB89712
        depends on LEDS
        default y if ARCH_EBSA110
        help
@@ -445,8 +446,7 @@ config LEDS_TIMER
          will overrule the CPU usage LED.
 
 config LEDS_CPU
-       bool "CPU usage LED" if (!ARCH_CDB89712 && !ARCH_EBSA110 && \
-                       !ARCH_OMAP) || MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
+       bool "CPU usage LED" if (!ARCH_CDB89712 && !ARCH_EBSA110)
        depends on LEDS
        help
          If you say Y here, the red LED will be used to give a good real
@@ -758,6 +758,8 @@ source "drivers/usb/Kconfig"
 
 source "drivers/mmc/Kconfig"
 
+source "drivers/ssi/Kconfig"
+
 endmenu
 
 source "fs/Kconfig"
index 114cda7f1b73fc1520cf3e197f27d2aca0e59019..dd3f75c4ef2c6cd3b572a3b91a167ca59a0bf038 100644 (file)
@@ -54,7 +54,7 @@ tune-$(CONFIG_CPU_ARM926T)    :=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)       :=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)      :=-mtune=strongarm1100
 tune-$(CONFIG_CPU_XSCALE)      :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
-tune-$(CONFIG_CPU_V6)          :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
+tune-$(CONFIG_CPU_V6)          :=$(call cc-option,-mtune=arm1136jf-s,-mtune=arm1136jfs)
 
 # Need -Uarm for gcc < 3.x
 CFLAGS_ABI     :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
@@ -93,6 +93,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
  machine-$(CONFIG_ARCH_IXP4XX)    := ixp4xx
  machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
  machine-$(CONFIG_ARCH_OMAP1)     := omap1
+ machine-$(CONFIG_ARCH_OMAP2)     := omap2
   incdir-$(CONFIG_ARCH_OMAP)      := omap
  machine-$(CONFIG_ARCH_S3C2410)           := s3c2410
  machine-$(CONFIG_ARCH_LH7A40X)           := lh7a40x
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
new file mode 100644 (file)
index 0000000..171a085
--- /dev/null
@@ -0,0 +1,2 @@
+Image
+zImage
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
new file mode 100644 (file)
index 0000000..aefee20
--- /dev/null
@@ -0,0 +1 @@
+piggy.gz
index 6b505ce41a75623765dbf3e78ba527f36e1f9178..f9b05d80a0825b089ea8d0338251a8596142b0cd 100644 (file)
@@ -51,7 +51,11 @@ OBJS         += head-sharpsl.o
 endif
 
 ifeq ($(CONFIG_DEBUG_ICEDCC),y)
-OBJS            += ice-dcc.o
+OBJS           += ice-dcc.o
+endif
+
+ifeq ($(CONFIG_MACH_OMAP_PERSEUS2),y)
+OBJS           += head-omap.o
 endif
 
 ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
diff --git a/arch/arm/boot/compressed/head-omap.S b/arch/arm/boot/compressed/head-omap.S
new file mode 100644 (file)
index 0000000..440e9a5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * linux/arch/arm/boot/compressed/head-omap.S
+ *
+ * OMAP specific tweaks.  This is merged into head.S by the linker.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/mach-types.h>
+
+               .section        ".start", "ax"
+
+__OMAP_start:
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+               /* support for booting without u-boot */
+               mov     r7, #(MACH_TYPE_OMAP_PERSEUS2 & ~0xf)
+               orr     r7, r7, #(MACH_TYPE_OMAP_PERSEUS2 & 0xf)
+#endif
index 7c7f475e213ea3f85779165679e06feb1aea7109..029c5d3f132b6816cacb30e425f655d8173447b6 100644 (file)
                add     \rb, \rb, #0x00010000   @ Ser1
 #  endif
                .endm
+#elif defined(CONFIG_ARCH_OMAP2)
+               .macro  loadsp, rb
+               mov     \rb, #0x48000000        @ physical base address
+               add     \rb, \rb, #0x0006a000
+#ifdef CONFIG_OMAP_LL_DEBUG_UART2
+               add     \rb, \rb, #0x00002000
+#endif
+#ifdef CONFIG_OMAP_LL_DEBUG_UART3
+               add     \rb, \rb, #0x00004000
+#endif
+               .endm
+               .macro  writeb, rb
+               strb    \rb, [r3]
+               .endm
 #elif defined(CONFIG_ARCH_IOP331)
                .macro loadsp, rb
                 mov    \rb, #0xff000000
diff --git a/arch/arm/configs/omap_generic_1510_defconfig b/arch/arm/configs/omap_generic_1510_defconfig
new file mode 100644 (file)
index 0000000..5091946
--- /dev/null
@@ -0,0 +1,851 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ADIFCC is not set
+# CONFIG_ARCH_ANAKIN is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SHARK is not set
+CONFIG_ARCH_OMAP=y
+
+#
+# CLPS711X/EP721X Implementations
+#
+
+#
+# Epxa10db
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# IOP3xx Implementation Options
+#
+# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IOP321 is not set
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Intel PXA250/210 Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP15XX=y
+# CONFIG_ARCH_OMAP1610 is not set
+# CONFIG_OMAP_INNOVATOR is not set
+CONFIG_MACH_OMAP_GENERIC=y
+# CONFIG_INNOVATOR_MISSED_IRQS is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP1510_PM is not set
+CONFIG_OMAP_ARM_168MHZ=y
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM925T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_WRITETHROUGH=y
+
+#
+# General setup
+#
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_PM=y
+CONFIG_PREEMPT=y
+# CONFIG_APM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="mem=64M console=ttyS2,115200 root=0803 ro init=/bin/sh"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_DCSSBLK is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_SMC9194 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_REPORT_LUNS=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+CONFIG_OMAP_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_VELLEMAN is not set
+CONFIG_I2C_OMAP1610=y
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BROKEN_RFD=y
+CONFIG_MMC_OMAP=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811HS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_XPAD is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_BRLVGER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
diff --git a/arch/arm/configs/omap_generic_1610_defconfig b/arch/arm/configs/omap_generic_1610_defconfig
new file mode 100644 (file)
index 0000000..b772e7e
--- /dev/null
@@ -0,0 +1,883 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3-omap1
+# Mon Oct  4 10:14:44 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# TI OMAP Implementations
+#
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+CONFIG_ARCH_OMAP_OTG=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_OMAP_H2 is not set
+# CONFIG_MACH_OMAP_H3 is not set
+# CONFIG_MACH_OMAP_H4 is not set
+# CONFIG_MACH_OMAP_OSK is not set
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_ARM_192MHZ=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# General setup
+#
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_PM=y
+CONFIG_PREEMPT=y
+# CONFIG_APM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="mem=64M console=ttyS2,115200 root=0803 ro init=/bin/sh"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMC9194 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_8250_OMAP is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_OMAP is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_GPIOEXPANDER_OMAP is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811HS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+# CONFIG_OMAP_UWIRE is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BROKEN_RFD=y
+CONFIG_MMC_OMAP=y
+# CONFIG_MMC_OMAP16XX_BLOCK1 is not set
+CONFIG_MMC_OMAP16XX_BLOCK2=y
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/omap_generic_1710_defconfig b/arch/arm/configs/omap_generic_1710_defconfig
new file mode 100644 (file)
index 0000000..579cff1
--- /dev/null
@@ -0,0 +1,853 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3-omap1
+# Mon Oct  4 10:14:57 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# TI OMAP Implementations
+#
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+CONFIG_ARCH_OMAP_OTG=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_OMAP_H2 is not set
+# CONFIG_MACH_OMAP_H3 is not set
+# CONFIG_MACH_OMAP_H4 is not set
+# CONFIG_MACH_OMAP_OSK is not set
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_BOOT_TAG=y
+# CONFIG_OMAP_BOOT_REASON is not set
+# CONFIG_OMAP_MUX is not set
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP_ARM_192MHZ=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# General setup
+#
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_PM=y
+# CONFIG_PREEMPT is not set
+# CONFIG_APM is not set
+CONFIG_ARTHUR=y
+CONFIG_CMDLINE="mem=64M console=tty0 console=ttyS2,115200 root=0801"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMC9194 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_8250_OMAP=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_OMAP_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+CONFIG_NLS_CODEPAGE_852=y
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811HS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_ALI_M5632=y
+# CONFIG_USB_AN2720 is not set
+# CONFIG_USB_BELKIN is not set
+# CONFIG_USB_GENESYS is not set
+# CONFIG_USB_NET1080 is not set
+# CONFIG_USB_PL2301 is not set
+
+#
+# Intelligent USB Devices/Gadgets
+#
+# CONFIG_USB_ARMLINUX is not set
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_ZAURUS is not set
+# CONFIG_USB_CDCETHER is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+# CONFIG_OMAP_UWIRE is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BROKEN_RFD is not set
+CONFIG_MMC_OMAP=y
+# CONFIG_MMC_OMAP16XX_BLOCK1 is not set
+CONFIG_MMC_OMAP16XX_BLOCK2=y
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_WAITQ=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SELINUX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/omap_generic_2420_defconfig b/arch/arm/configs/omap_generic_2420_defconfig
new file mode 100644 (file)
index 0000000..94d4659
--- /dev/null
@@ -0,0 +1,555 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-rc6-omap1
+# Thu Aug 11 10:05:10 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+# CONFIG_OMAP_BOOT_REASON is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# OMAP Core Type
+#
+CONFIG_ARCH_OMAP24XX=y
+CONFIG_ARCH_OMAP2420=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_H4 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x10C08000
+CONFIG_ZBOOT_ROM_BSS=0x10200000
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+# CONFIG_OMAP_TSC2101 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
index 4198677cd394c81cebbd5eb068e82fb4fc02e9fa..1cf919a752ca69a1e207d4c6725384908f63c72b 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13
-# Mon Sep  5 18:07:12 2005
+# Linux kernel version: 2.6.14-rc4-omap1
+# Tue Oct 18 17:57:57 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -15,13 +15,13 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -31,8 +31,10 @@ CONFIG_SYSCTL=y
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -96,12 +98,14 @@ CONFIG_ARCH_OMAP1=y
 # OMAP Feature Selections
 #
 # CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+# CONFIG_OMAP_BOOT_REASON is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
 CONFIG_OMAP_MUX=y
-# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_DEBUG=y
 CONFIG_OMAP_MUX_WARNINGS=y
-# CONFIG_OMAP_MPU_TIMER is not set
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
 # CONFIG_OMAP_DM_TIMER is not set
 CONFIG_OMAP_LL_DEBUG_UART1=y
 # CONFIG_OMAP_LL_DEBUG_UART2 is not set
@@ -112,7 +116,7 @@ CONFIG_OMAP_SERIAL_WAKE=y
 # OMAP Core Type
 #
 # CONFIG_ARCH_OMAP730 is not set
-# CONFIG_ARCH_OMAP1510 is not set
+# CONFIG_ARCH_OMAP15XX is not set
 CONFIG_ARCH_OMAP16XX=y
 
 #
@@ -129,11 +133,12 @@ CONFIG_MACH_OMAP_H2=y
 #
 # CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
 # CONFIG_OMAP_ARM_216MHZ is not set
-CONFIG_OMAP_ARM_192MHZ=y
+# CONFIG_OMAP_ARM_192MHZ is not set
 # CONFIG_OMAP_ARM_168MHZ is not set
 # CONFIG_OMAP_ARM_120MHZ is not set
-# CONFIG_OMAP_ARM_60MHZ is not set
+CONFIG_OMAP_ARM_60MHZ=y
 # CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
 
 #
 # Processor Type
@@ -168,8 +173,8 @@ CONFIG_ISA_DMA_API=y
 #
 # Kernel Features
 #
-CONFIG_PREEMPT=y
-CONFIG_NO_IDLE_HZ=y
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -177,7 +182,10 @@ CONFIG_FLATMEM_MANUAL=y
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_LEDS is not set
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+# CONFIG_LEDS_CPU is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -185,24 +193,13 @@ CONFIG_ALIGNMENT_TRAP=y
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 root=0801 ro init=/bin/sh"
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 root=/dev/ram0 rw initrd=0x10600000,8M ramdisk_size=8192"
 # CONFIG_XIP_KERNEL is not set
 
 #
 # CPU Frequency scaling
 #
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_STAT=y
-# CONFIG_CPU_FREQ_STAT_DETAILS is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
-# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ is not set
 
 #
 # Floating point emulation
@@ -227,8 +224,7 @@ CONFIG_BINFMT_AOUT=y
 #
 # Power management options
 #
-CONFIG_PM=y
-# CONFIG_APM is not set
+# CONFIG_PM is not set
 
 #
 # Networking
@@ -258,13 +254,18 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
@@ -291,6 +292,7 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -302,11 +304,85 @@ CONFIG_TCP_CONG_BIC=y
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+CONFIG_DEBUG_DRIVER=y
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=3
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
 
 #
 # Parallel port support
@@ -324,11 +400,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -338,43 +414,13 @@ CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # SCSI device support
 #
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-# CONFIG_BLK_DEV_SD is not set
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -403,6 +449,11 @@ CONFIG_NETDEVICES=y
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -528,8 +579,16 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_OMAP_WATCHDOG is not set
+# CONFIG_OMAP_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -545,20 +604,91 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 #
 # I2C support
 #
-# CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_OMAP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 CONFIG_ISP1301_OMAP=y
+CONFIG_TPS65010=y
+# CONFIG_SENSORS_TLV320AIC23 is not set
+# CONFIG_GPIOEXPANDER_OMAP is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
 
 #
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -576,11 +706,15 @@ CONFIG_FB=y
 # CONFIG_FB_CFB_FILLRECT is not set
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_SOFT_CURSOR=y
 # CONFIG_FB_MACMODES is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_DMA_TUNE is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -589,17 +723,9 @@ CONFIG_FB_MODE_HELPERS=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
+# CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_7x14 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_10x18 is not set
 
 #
 # Logo configuration
@@ -613,28 +739,124 @@ CONFIG_LOGO_LINUX_CLUT224=y
 #
 # Sound
 #
-CONFIG_SOUND=y
+# CONFIG_SOUND is not set
 
 #
-# Advanced Linux Sound Architecture
+# USB support
 #
-# CONFIG_SND is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
 
 #
-# Open Sound System
+# Miscellaneous USB options
 #
-CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_AD1980 is not set
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
 
 #
-# USB support
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+CONFIG_USB_TEST=y
+
+#
+# USB DSL modem support
 #
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -662,6 +884,12 @@ CONFIG_USB_ETH_RNDIS=y
 #
 # CONFIG_MMC is not set
 
+#
+# Synchronous Serial Interfaces (SSI)
+#
+CONFIG_OMAP_UWIRE=y
+# CONFIG_OMAP_TSC2101 is not set
+
 #
 # File systems
 #
@@ -673,10 +901,6 @@ CONFIG_EXT2_FS=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
@@ -685,6 +909,7 @@ CONFIG_INOTIFY=y
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -706,10 +931,10 @@ CONFIG_FAT_DEFAULT_CODEPAGE=437
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -721,6 +946,14 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=2
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -732,24 +965,22 @@ CONFIG_CRAMFS=y
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -810,11 +1041,23 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
 
 #
 # Security options
@@ -825,31 +1068,7 @@ CONFIG_FRAME_POINTER=y
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -859,6 +1078,8 @@ CONFIG_CRYPTO_DES=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/omap_h3_1710_defconfig b/arch/arm/configs/omap_h3_1710_defconfig
new file mode 100644 (file)
index 0000000..a32749d
--- /dev/null
@@ -0,0 +1,1048 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc4-omap1
+# Tue Oct 18 17:58:27 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+# CONFIG_OMAP_DM_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_OMAP_H2 is not set
+CONFIG_MACH_OMAP_H3=y
+# CONFIG_MACH_OMAP_OSK is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+# CONFIG_OMAP_ARM_216MHZ is not set
+# CONFIG_OMAP_ARM_192MHZ is not set
+CONFIG_OMAP_ARM_168MHZ=y
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x10C08000
+CONFIG_ZBOOT_ROM_BSS=0x10200000
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 initrd=0x10A00000,8M root=/dev/ram0 rw ip=dhcp devfs=mount"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=y
+
+#
+# IrDA protocols
+#
+# CONFIG_IRLAN is not set
+# CONFIG_IRNET is not set
+# CONFIG_IRCOMM is not set
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+CONFIG_OMAP1610_IR=y
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VIA_FIR is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_OMAP_WATCHDOG is not set
+# CONFIG_OMAP_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_OMAP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+CONFIG_ISP1301_OMAP=m
+CONFIG_TPS65010=y
+# CONFIG_SENSORS_TLV320AIC23 is not set
+CONFIG_GPIOEXPANDER_OMAP=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_VIDEO_OMAP_CAMERA is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_OMAP is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BROKEN_RFD is not set
+# CONFIG_MMC_BULKTRANSFER is not set
+CONFIG_MMC_OMAP=y
+# CONFIG_MMC_WBSD is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+CONFIG_OMAP_UWIRE=y
+# CONFIG_OMAP_TSC2101 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/omap_h4_2420_defconfig b/arch/arm/configs/omap_h4_2420_defconfig
new file mode 100644 (file)
index 0000000..d841777
--- /dev/null
@@ -0,0 +1,936 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc4-omap1
+# Tue Oct 18 17:58:50 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_BOOT_TAG=y
+# CONFIG_OMAP_BOOT_REASON is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# OMAP Core Type
+#
+CONFIG_ARCH_OMAP24XX=y
+CONFIG_ARCH_OMAP2420=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP_H4=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 rw console=ttyS0,115200n8 initrd=0x80600000,8M ramdisk_size=8192"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+# CONFIG_OMAP_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_OMAP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_TLV320AIC23 is not set
+CONFIG_MENELAUS=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BROKEN_RFD=y
+CONFIG_MMC_BULKTRANSFER=y
+CONFIG_MMC_OMAP=y
+# CONFIG_MMC_WBSD is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+# CONFIG_OMAP_TSC2101 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/omap_innovator_1510_defconfig b/arch/arm/configs/omap_innovator_1510_defconfig
new file mode 100644 (file)
index 0000000..28c087e
--- /dev/null
@@ -0,0 +1,1082 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc4-omap1
+# Tue Oct 18 17:55:19 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+CONFIG_ARCH_OMAP15XX=y
+# CONFIG_ARCH_OMAP16XX is not set
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP_INNOVATOR=y
+# CONFIG_MACH_VOICEBLUE is not set
+# CONFIG_MACH_NETSTAR is not set
+# CONFIG_MACH_OMAP_PALMTE is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+CONFIG_OMAP_ARM_168MHZ=y
+# CONFIG_OMAP_ARM_150MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM925T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_WRITETHROUGH=y
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200n8 root=/dev/nfs ip=bootp noinitrd"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+CONFIG_OMAP_PS2=m
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_OMAP is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+# CONFIG_USB_STORAGE_USBAT is not set
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=y
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BROKEN_RFD=y
+# CONFIG_MMC_BULKTRANSFER is not set
+CONFIG_MMC_OMAP=y
+# CONFIG_MMC_WBSD is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+# CONFIG_OMAP_UWIRE is not set
+# CONFIG_OMAP_TSC2101 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/omap_innovator_1610_defconfig b/arch/arm/configs/omap_innovator_1610_defconfig
new file mode 100644 (file)
index 0000000..7baf3bc
--- /dev/null
@@ -0,0 +1,750 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc4-omap1
+# Tue Oct 18 17:55:48 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+# CONFIG_OMAP_DM_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP_INNOVATOR=y
+# CONFIG_MACH_OMAP_H2 is not set
+# CONFIG_MACH_OMAP_H3 is not set
+# CONFIG_MACH_OMAP_OSK is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+# CONFIG_OMAP_ARM_216MHZ is not set
+CONFIG_OMAP_ARM_192MHZ=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_WRITETHROUGH=y
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=tty0 console=ttyS0,115200 initrd=0x10200000,8M root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_OMAP_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_OMAP_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+# CONFIG_OMAP_UWIRE is not set
+# CONFIG_OMAP_TSC2101 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/omap_osk_5912_defconfig b/arch/arm/configs/omap_osk_5912_defconfig
new file mode 100644 (file)
index 0000000..d190420
--- /dev/null
@@ -0,0 +1,995 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc4-omap1
+# Tue Oct 18 17:56:19 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_RESET_CLOCKS=y
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+# CONFIG_OMAP_DM_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+# CONFIG_ARCH_OMAP15XX is not set
+CONFIG_ARCH_OMAP16XX=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_OMAP_H2 is not set
+# CONFIG_MACH_OMAP_H3 is not set
+CONFIG_MACH_OMAP_OSK=y
+# CONFIG_OMAP_OSK_MISTRAL is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+# CONFIG_OMAP_ARM_216MHZ is not set
+CONFIG_OMAP_ARM_192MHZ=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_OMAP_CF=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_NO_IDLE_HZ=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x10400000,8M root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_OMAP=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_OMAP_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_OMAP_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_OMAP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TPS65010=y
+# CONFIG_SENSORS_TLV320AIC23 is not set
+# CONFIG_GPIOEXPANDER_OMAP is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+CONFIG_OMAP_UWIRE=y
+CONFIG_OMAP_TSC2101=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/omap_perseus2_730_defconfig b/arch/arm/configs/omap_perseus2_730_defconfig
new file mode 100644 (file)
index 0000000..7e08ad3
--- /dev/null
@@ -0,0 +1,811 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-rc4-omap1
+# Tue Oct 18 17:57:11 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+CONFIG_ARCH_OMAP730=y
+# CONFIG_ARCH_OMAP15XX is not set
+# CONFIG_ARCH_OMAP16XX is not set
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP_PERSEUS2=y
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+# CONFIG_OMAP_ARM_195MHZ is not set
+CONFIG_OMAP_ARM_182MHZ=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 ip=dhcp"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+CONFIG_MTD_OMAP_NOR=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_OMAP=y
+# CONFIG_MTD_NAND_TOTO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_LCDC_INTERNAL=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+CONFIG_FB_VIRTUAL=y
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+CONFIG_OMAP_UWIRE=y
+# CONFIG_OMAP_TSC2101 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/palmte_defconfig b/arch/arm/configs/palmte_defconfig
new file mode 100644 (file)
index 0000000..26a8999
--- /dev/null
@@ -0,0 +1,648 @@
+#
+# Palm Tungsten E default kernel configuration
+# Created by Romain Goyet <palmtelinux-developpers@lists.sf.net>
+# Linux kernel version: 2.6.13-rc6-omap1
+# Fri Aug 26 16:01:18 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_HOTPLUG=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+CONFIG_ARCH_OMAP15XX=y
+# CONFIG_ARCH_OMAP16XX is not set
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+# CONFIG_MACH_VOICEBLUE is not set
+# CONFIG_MACH_NETSTAR is not set
+CONFIG_MACH_OMAP_PALMTE=y
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
+# CONFIG_OMAP_ARM_168MHZ is not set
+# CONFIG_OMAP_ARM_150MHZ is not set
+# CONFIG_OMAP_ARM_120MHZ is not set
+# CONFIG_OMAP_ARM_60MHZ is not set
+# CONFIG_OMAP_ARM_30MHZ is not set
+# CONFIG_OMAP_DSP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM925T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+# CONFIG_I2C_SENSOR is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+CONFIG_FB_OMAP_INTERNAL_LCDC=y
+# CONFIG_FB_OMAP_EXTERNAL_LCDC is not set
+# CONFIG_FB_OMAP_DMA_TUNE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+CONFIG_USB_GADGET_OMAP=y
+CONFIG_USB_OMAP=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=y
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BROKEN_RFD is not set
+# CONFIG_MMC_BULKTRANSFER is not set
+CONFIG_MMC_OMAP=y
+# CONFIG_MMC_WBSD is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+# CONFIG_OMAP_UWIRE is not set
+# CONFIG_OMAP_TSC2101 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
index 80c8e4c8cefa078650b7180f7581eeac93296ebf..fb654bc5499a94b6aaa0e3d58e0d5c2dd495d194 100644 (file)
@@ -171,7 +171,3 @@ SECTIONS
        .stab.indexstr 0 : { *(.stab.indexstr) }
        .comment 0 : { *(.comment) }
 }
-
-/* those must never be empty */
-ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
-ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
index 27fc2e8e5fca6d07cfa6659bc9562279de7084ac..a8d2d9aec3073243ab8bb824161593c308ca4828 100644 (file)
@@ -6,10 +6,10 @@ config ARCH_OMAP730
        bool "OMAP730 Based System"
        select ARCH_OMAP_OTG
 
-config ARCH_OMAP1510
+config ARCH_OMAP15XX
        depends on ARCH_OMAP1
        default y
-       bool "OMAP1510 Based System"
+       bool "OMAP15xx Based System"
 
 config ARCH_OMAP16XX
        depends on ARCH_OMAP1
@@ -21,7 +21,7 @@ comment "OMAP Board Type"
 
 config MACH_OMAP_INNOVATOR
        bool "TI Innovator"
-       depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX)
+       depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
        help
           TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
           have such a board.
@@ -64,20 +64,30 @@ config MACH_OMAP_PERSEUS2
 
 config MACH_VOICEBLUE
        bool "Voiceblue"
-       depends on ARCH_OMAP1 && ARCH_OMAP1510
+       depends on ARCH_OMAP1 && ARCH_OMAP15XX
        help
          Support for Voiceblue GSM/VoIP gateway. Say Y here if you have
          such a board.
 
 config MACH_NETSTAR
        bool "NetStar"
-       depends on ARCH_OMAP1 && ARCH_OMAP1510
+       depends on ARCH_OMAP1 && ARCH_OMAP15XX
        help
          Support for NetStar PBX. Say Y here if you have such a board.
 
+config MACH_OMAP_PALMTE
+       bool "Palm Tungsten E"
+       depends on ARCH_OMAP1 && ARCH_OMAP15XX
+       help
+          Support for the Palm Tungsten E PDA. Currently only the LCD panel
+          is supported. To boot the kernel, you'll need a PalmOS compatible
+          bootloader; check out http://palmtelinux.sourceforge.net for more
+          informations.
+          Say Y here if you have such a PDA, say NO otherwise.
+
 config MACH_OMAP_GENERIC
        bool "Generic OMAP board"
-       depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX)
+       depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
        help
           Support for generic OMAP-1510, 1610 or 1710 board with
           no FPGA. Can be used as template for porting Linux to
@@ -121,32 +131,34 @@ config OMAP_ARM_182MHZ
 
 config OMAP_ARM_168MHZ
        bool "OMAP ARM 168 MHz CPU"
-       depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730)
+       depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
        help
           Enable 168MHz clock for OMAP CPU. If unsure, say N.
 
 config OMAP_ARM_150MHZ
        bool "OMAP ARM 150 MHz CPU"
-       depends on ARCH_OMAP1 && ARCH_OMAP1510
+       depends on ARCH_OMAP1 && ARCH_OMAP15XX
        help
          Enable 150MHz clock for OMAP CPU. If unsure, say N.
 
 config OMAP_ARM_120MHZ
        bool "OMAP ARM 120 MHz CPU"
-       depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730)
+       depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
        help
           Enable 120MHz clock for OMAP CPU. If unsure, say N.
 
 config OMAP_ARM_60MHZ
        bool "OMAP ARM 60 MHz CPU"
-       depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730)
+       depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
         default y
        help
           Enable 60MHz clock for OMAP CPU. If unsure, say Y.
 
 config OMAP_ARM_30MHZ
        bool "OMAP ARM 30 MHz CPU"
-       depends on ARCH_OMAP1 && (ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730)
+       depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
        help
           Enable 30MHz clock for OMAP CPU. If unsure, say N.
 
+source "arch/arm/plat-omap/dsp/Kconfig"
+
index 181a93deaaee4fa9cca5cbd5fbbca498e0930f3f..b0b00156faaefbaf00296bdc0856a427b13596d8 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := io.o id.o irq.o time.o serial.o devices.o
+obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o
 led-y := leds.o
 
 # Specific board support
@@ -15,8 +15,9 @@ obj-$(CONFIG_MACH_OMAP_OSK)           += board-osk.o
 obj-$(CONFIG_MACH_OMAP_H3)             += board-h3.o
 obj-$(CONFIG_MACH_VOICEBLUE)           += board-voiceblue.o
 obj-$(CONFIG_MACH_NETSTAR)             += board-netstar.o
+obj-$(CONFIG_MACH_OMAP_PALMTE)         += board-palmte.o
 
-ifeq ($(CONFIG_ARCH_OMAP1510),y)
+ifeq ($(CONFIG_ARCH_OMAP15XX),y)
 # Innovator-1510 FPGA
 obj-$(CONFIG_MACH_OMAP_INNOVATOR)      += fpga.o
 endif
index c209c7172a9aedf295c725e5ecf79bbb0b8ea02f..4b292e93fbe23563e2a6d8297cad7a3d68427581 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -28,8 +28,6 @@
 #include <asm/arch/board.h>
 #include <asm/arch/common.h>
 
-static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
-
 static void __init omap_generic_init_irq(void)
 {
        omap_init_irq();
@@ -37,7 +35,7 @@ static void __init omap_generic_init_irq(void)
 
 /* assume no Mini-AB port */
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_usb_config generic1510_usb_config __initdata = {
        .register_host  = 1,
        .register_dev   = 1,
@@ -76,21 +74,19 @@ static struct omap_mmc_config generic_mmc_config __initdata = {
 
 #endif
 
+static struct omap_uart_config generic_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
 static struct omap_board_config_kernel generic_config[] = {
        { OMAP_TAG_USB,           NULL },
        { OMAP_TAG_MMC,           &generic_mmc_config },
+       { OMAP_TAG_UART,        &generic_uart_config },
 };
 
 static void __init omap_generic_init(void)
 {
-       const struct omap_uart_config *uart_conf;
-
-       /*
-        * Make sure the serial ports are muxed on at this point.
-        * You have to mux them off in device drivers later on
-        * if not needed.
-        */
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                generic_config[0].data = &generic1510_usb_config;
        }
@@ -101,20 +97,9 @@ static void __init omap_generic_init(void)
        }
 #endif
 
-       uart_conf = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
-       if (uart_conf != NULL) {
-               unsigned int enabled_ports, i;
-
-               enabled_ports = uart_conf->enabled_uarts;
-               for (i = 0; i < 3; i++) {
-                       if (!(enabled_ports & (1 << i)))
-                               generic_serial_ports[i] = 0;
-               }
-       }
-
        omap_board_config = generic_config;
        omap_board_config_size = ARRAY_SIZE(generic_config);
-       omap_serial_init(generic_serial_ports);
+       omap_serial_init();
 }
 
 static void __init omap_generic_map_io(void)
index 4ee6bd8a50b8b105699e4c5698883bcd4526647f..a07e2c9307fa338896ecca300dc88033a8922885 100644 (file)
@@ -40,8 +40,6 @@
 
 extern int omap_gpio_init(void);
 
-static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
-
 static struct mtd_partition h2_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
@@ -160,9 +158,20 @@ static struct omap_mmc_config h2_mmc_config __initdata = {
        },
 };
 
+static struct omap_uart_config h2_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_lcd_config h2_lcd_config __initdata = {
+       .panel_name     = "h2",
+       .ctrl_name      = "internal",
+};
+
 static struct omap_board_config_kernel h2_config[] = {
        { OMAP_TAG_USB,           &h2_usb_config },
        { OMAP_TAG_MMC,           &h2_mmc_config },
+       { OMAP_TAG_UART,        &h2_uart_config },
+       { OMAP_TAG_LCD,         &h2_lcd_config },
 };
 
 static void __init h2_init(void)
@@ -180,12 +189,12 @@ static void __init h2_init(void)
        platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
        omap_board_config = h2_config;
        omap_board_config_size = ARRAY_SIZE(h2_config);
+       omap_serial_init();
 }
 
 static void __init h2_map_io(void)
 {
        omap_map_common_io();
-       omap_serial_init(h2_serial_ports);
 }
 
 MACHINE_START(OMAP_H2, "TI-H2")
index fc824361430d86951f184e8b23f82cee8ee07928..668e278433c28701762f28b9531b0ecc489406f8 100644 (file)
@@ -41,8 +41,6 @@
 
 extern int omap_gpio_init(void);
 
-static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
-
 static struct mtd_partition h3_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
@@ -168,9 +166,20 @@ static struct omap_mmc_config h3_mmc_config __initdata = {
        },
 };
 
+static struct omap_uart_config h3_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_lcd_config h3_lcd_config __initdata = {
+       .panel_name     = "h3",
+       .ctrl_name      = "internal",
+};
+
 static struct omap_board_config_kernel h3_config[] = {
-       { OMAP_TAG_USB,  &h3_usb_config },
-       { OMAP_TAG_MMC,  &h3_mmc_config },
+       { OMAP_TAG_USB,         &h3_usb_config },
+       { OMAP_TAG_MMC,         &h3_mmc_config },
+       { OMAP_TAG_UART,        &h3_uart_config },
+       { OMAP_TAG_LCD,         &h3_lcd_config },
 };
 
 static void __init h3_init(void)
@@ -180,6 +189,7 @@ static void __init h3_init(void)
        (void) platform_add_devices(devices, ARRAY_SIZE(devices));
        omap_board_config = h3_config;
        omap_board_config_size = ARRAY_SIZE(h3_config);
+       omap_serial_init();
 }
 
 static void __init h3_init_smc91x(void)
@@ -201,7 +211,6 @@ void h3_init_irq(void)
 static void __init h3_map_io(void)
 {
        omap_map_common_io();
-       omap_serial_init(h3_serial_ports);
 }
 
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
index a2eac853b2da863fe0f0a59c4bfc90dafa6c092f..95f1ff36cdcbc0b3e81ee5a2f7f298bcf35c7d05 100644 (file)
@@ -36,8 +36,6 @@
 #include <asm/arch/usb.h>
 #include <asm/arch/common.h>
 
-static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
-
 static struct mtd_partition innovator_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
@@ -99,7 +97,7 @@ static struct platform_device innovator_flash_device = {
        .resource       = &innovator_flash_resource,
 };
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc innovator1510_io_desc[] __initdata = {
@@ -136,7 +134,7 @@ static struct platform_device *innovator1510_devices[] __initdata = {
        &innovator1510_smc91x_device,
 };
 
-#endif /* CONFIG_ARCH_OMAP1510 */
+#endif /* CONFIG_ARCH_OMAP15XX */
 
 #ifdef CONFIG_ARCH_OMAP16XX
 
@@ -185,7 +183,7 @@ void innovator_init_irq(void)
 {
        omap_init_irq();
        omap_gpio_init();
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                omap1510_fpga_init_irq();
        }
@@ -193,7 +191,7 @@ void innovator_init_irq(void)
        innovator_init_smc91x();
 }
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_usb_config innovator1510_usb_config __initdata = {
        /* for bundled non-standard host and peripheral cables */
        .hmc_mode       = 4,
@@ -205,6 +203,11 @@ static struct omap_usb_config innovator1510_usb_config __initdata = {
        .register_dev   = 1,
        .pins[0]        = 2,
 };
+
+static struct omap_lcd_config innovator1510_lcd_config __initdata = {
+       .panel_name     = "inn1510",
+       .ctrl_name      = "internal",
+};
 #endif
 
 #ifdef CONFIG_ARCH_OMAP16XX
@@ -222,6 +225,11 @@ static struct omap_usb_config h2_usb_config __initdata = {
 
        .pins[1]        = 3,
 };
+
+static struct omap_lcd_config innovator1610_lcd_config __initdata = {
+       .panel_name     = "inn1610",
+       .ctrl_name      = "internal",
+};
 #endif
 
 static struct omap_mmc_config innovator_mmc_config __initdata = {
@@ -234,14 +242,20 @@ static struct omap_mmc_config innovator_mmc_config __initdata = {
        },
 };
 
+static struct omap_uart_config innovator_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
 static struct omap_board_config_kernel innovator_config[] = {
        { OMAP_TAG_USB,         NULL },
+       { OMAP_TAG_LCD,         NULL },
        { OMAP_TAG_MMC,         &innovator_mmc_config },
+       { OMAP_TAG_UART,        &innovator_uart_config },
 };
 
 static void __init innovator_init(void)
 {
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
        }
@@ -252,23 +266,28 @@ static void __init innovator_init(void)
        }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1510
-       if (cpu_is_omap1510())
+#ifdef CONFIG_ARCH_OMAP15XX
+       if (cpu_is_omap1510()) {
                innovator_config[0].data = &innovator1510_usb_config;
+               innovator_config[1].data = &innovator1510_lcd_config;
+       }
 #endif
 #ifdef CONFIG_ARCH_OMAP16XX
-       if (cpu_is_omap1610())
+       if (cpu_is_omap1610()) {
                innovator_config[0].data = &h2_usb_config;
+               innovator_config[1].data = &innovator1610_lcd_config;
+       }
 #endif
        omap_board_config = innovator_config;
        omap_board_config_size = ARRAY_SIZE(innovator_config);
+       omap_serial_init();
 }
 
 static void __init innovator_map_io(void)
 {
        omap_map_common_io();
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
                udelay(10);     /* Delay needed for FPGA */
@@ -280,7 +299,6 @@ static void __init innovator_map_io(void)
                       fpga_read(OMAP1510_FPGA_BOARD_REV));
        }
 #endif
-       omap_serial_init(innovator_serial_ports);
 }
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
index c851c2e4dfcb74cc97f988feb93308f53d159500..0448fa7de8a416a48cd1977f29858be54e67c078 100644 (file)
@@ -55,6 +55,14 @@ static struct platform_device *netstar_devices[] __initdata = {
        &netstar_smc91x_device,
 };
 
+static struct omap_uart_config netstar_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_board_config_kernel netstar_config[] = {
+       { OMAP_TAG_UART,        &netstar_uart_config },
+};
+
 static void __init netstar_init_irq(void)
 {
        omap_init_irq();
@@ -92,14 +100,15 @@ static void __init netstar_init(void)
        /* Switch off red LED */
        omap_writeb(0x00, OMAP_LPG1_PMR);       /* Disable clock */
        omap_writeb(0x80, OMAP_LPG1_LCR);
-}
 
-static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+       omap_board_config = netstar_config;
+       omap_board_config_size = ARRAY_SIZE(netstar_config);
+       omap_serial_init();
+}
 
 static void __init netstar_map_io(void)
 {
        omap_map_common_io();
-       omap_serial_init(omap_serial_ports);
 }
 
 #define MACHINE_PANICED                1
index a88524e7c315ba1f95a423f5408d5250214cf540..e990e1bc16696cea8e0b53e1b48409c72e33fbb5 100644 (file)
@@ -46,8 +46,6 @@
 #include <asm/arch/tc.h>
 #include <asm/arch/common.h>
 
-static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
-
 static struct mtd_partition osk_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
@@ -155,7 +153,7 @@ static void __init osk_init_smc91x(void)
        }
 
        /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */
-       EMIFS_CCS(1) |= 0x2;
+       EMIFS_CCS(1) |= 0x3;
 }
 
 static void __init osk_init_cf(void)
@@ -193,8 +191,19 @@ static struct omap_usb_config osk_usb_config __initdata = {
        .pins[0]        = 2,
 };
 
+static struct omap_uart_config osk_uart_config __initdata = {
+       .enabled_uarts = (1 << 0),
+};
+
+static struct omap_lcd_config osk_lcd_config __initdata = {
+       .panel_name     = "osk",
+       .ctrl_name      = "internal",
+};
+
 static struct omap_board_config_kernel osk_config[] = {
        { OMAP_TAG_USB,           &osk_usb_config },
+       { OMAP_TAG_UART,                &osk_uart_config },
+       { OMAP_TAG_LCD,                 &osk_lcd_config },
 };
 
 #ifdef CONFIG_OMAP_OSK_MISTRAL
@@ -254,13 +263,13 @@ static void __init osk_init(void)
        omap_board_config_size = ARRAY_SIZE(osk_config);
        USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
 
+       omap_serial_init();
        osk_mistral_init();
 }
 
 static void __init osk_map_io(void)
 {
        omap_map_common_io();
-       omap_serial_init(osk_serial_ports);
 }
 
 MACHINE_START(OMAP_OSK, "TI-OSK")
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
new file mode 100644 (file)
index 0000000..540b20d
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * linux/arch/arm/mach-omap1/board-palmte.c
+ *
+ * Modified from board-generic.c
+ *
+ * Support for the Palm Tungsten E PDA.
+ *
+ * Original version : Laurent Gonzalez
+ *
+ * Maintainters : http://palmtelinux.sf.net
+ *                palmtelinux-developpers@lists.sf.net
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/notifier.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include <asm/hardware/clock.h>
+
+static void __init omap_generic_init_irq(void)
+{
+       omap_init_irq();
+}
+
+static struct omap_usb_config palmte_usb_config __initdata = {
+       .register_dev   = 1,
+       .hmc_mode       = 0,
+       .pins[0]        = 3,
+};
+
+static struct omap_mmc_config palmte_mmc_config __initdata = {
+       .mmc [0] = {
+               .enabled        = 1,
+               .wire4          = 1,
+               .wp_pin         = OMAP_MPUIO(3),
+               .power_pin      = -1,
+               .switch_pin     = -1,
+       },
+};
+
+static struct omap_lcd_config palmte_lcd_config __initdata = {
+       .panel_name     = "palmte",
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel palmte_config[] = {
+       { OMAP_TAG_USB, &palmte_usb_config },
+       { OMAP_TAG_MMC, &palmte_mmc_config },
+       { OMAP_TAG_LCD, &palmte_lcd_config },
+};
+
+static void __init omap_generic_init(void)
+{
+       omap_board_config = palmte_config;
+       omap_board_config_size = ARRAY_SIZE(palmte_config);
+}
+
+static void __init omap_generic_map_io(void)
+{
+       omap_map_common_io();
+}
+
+MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
+       .phys_ram       = 0x10000000,
+       .phys_io        = 0xfff00000,
+       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
+       .boot_params    = 0x10000100,
+       .map_io         = omap_generic_map_io,
+       .init_irq       = omap_generic_init_irq,
+       .init_machine   = omap_generic_init,
+       .timer          = &omap_timer,
+MACHINE_END
index 354b157acb3a2071193c450630e846618db69020..bd900b7ab33cfdde0335252d376ad3209db16732 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/fpga.h>
 #include <asm/arch/common.h>
+#include <asm/arch/board.h>
 
 static struct resource smc91x_resources[] = {
        [0] = {
@@ -43,8 +44,6 @@ static struct resource smc91x_resources[] = {
        },
 };
 
-static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0};
-
 static struct mtd_partition p2_partitions[] = {
        /* bootloader (U-Boot, etc) in first sector */
        {
@@ -111,9 +110,27 @@ static struct platform_device *devices[] __initdata = {
        &smc91x_device,
 };
 
+static struct omap_uart_config perseus2_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1)),
+};
+
+static struct omap_lcd_config perseus2_lcd_config __initdata = {
+       .panel_name     = "p2",
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel perseus2_config[] = {
+       { OMAP_TAG_UART,        &perseus2_uart_config },
+       { OMAP_TAG_LCD,         &perseus2_lcd_config },
+};
+
 static void __init omap_perseus2_init(void)
 {
        (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       omap_board_config = perseus2_config;
+       omap_board_config_size = ARRAY_SIZE(perseus2_config);
+       omap_serial_init();
 }
 
 static void __init perseus2_init_smc91x(void)
@@ -131,7 +148,6 @@ void omap_perseus2_init_irq(void)
        omap_gpio_init();
        perseus2_init_smc91x();
 }
-
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
        {
@@ -179,7 +195,6 @@ static void __init omap_perseus2_map_io(void)
         * It is used as the Ethernet controller interrupt
         */
        omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9);
-       omap_serial_init(p2_serial_ports);
 }
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
index 3f018b296861e4def60cd01df13fb470a4fefd54..6f9a6220e78ac587254162fcb92651af2f4bdd42 100644 (file)
@@ -150,9 +150,14 @@ static struct omap_mmc_config voiceblue_mmc_config __initdata = {
        },
 };
 
+static struct omap_uart_config voiceblue_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
 static struct omap_board_config_kernel voiceblue_config[] = {
        { OMAP_TAG_USB, &voiceblue_usb_config },
        { OMAP_TAG_MMC, &voiceblue_mmc_config },
+       { OMAP_TAG_UART,        &voiceblue_uart_config },
 };
 
 static void __init voiceblue_init_irq(void)
@@ -191,6 +196,7 @@ static void __init voiceblue_init(void)
        platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
        omap_board_config = voiceblue_config;
        omap_board_config_size = ARRAY_SIZE(voiceblue_config);
+       omap_serial_init();
 
        /* There is a good chance board is going up, so enable power LED
         * (it is connected through invertor) */
@@ -198,12 +204,9 @@ static void __init voiceblue_init(void)
        omap_writeb(0x00, OMAP_LPG1_PMR);       /* Disable clock */
 }
 
-static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
-
 static void __init voiceblue_map_io(void)
 {
        omap_map_common_io();
-       omap_serial_init(omap_serial_ports);
 }
 
 #define MACHINE_PANICED                1
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
new file mode 100644 (file)
index 0000000..4277eee
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+ *  linux/arch/arm/mach-omap1/clock.c
+ *
+ *  Copyright (C) 2004 - 2005 Nokia corporation
+ *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ *  Modified to use omap shared clock framework by
+ *  Tony Lindgren <tony@atomide.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/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+#include <asm/arch/usb.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+
+#include "clock.h"
+
+__u32 arm_idlect1_mask;
+
+/*-------------------------------------------------------------------------
+ * Omap1 specific clock functions
+ *-------------------------------------------------------------------------*/
+
+static void omap1_watchdog_recalc(struct clk * clk)
+{
+       clk->rate = clk->parent->rate / 14;
+}
+
+static void omap1_uart_recalc(struct clk * clk)
+{
+       unsigned int val = omap_readl(clk->enable_reg);
+       if (val & clk->enable_bit)
+               clk->rate = 48000000;
+       else
+               clk->rate = 12000000;
+}
+
+static int omap1_clk_enable_dsp_domain(struct clk *clk)
+{
+       int retval;
+
+       retval = omap1_clk_use(&api_ck.clk);
+       if (!retval) {
+               retval = omap1_clk_enable(clk);
+               omap1_clk_unuse(&api_ck.clk);
+       }
+
+       return retval;
+}
+
+static void omap1_clk_disable_dsp_domain(struct clk *clk)
+{
+       if (omap1_clk_use(&api_ck.clk) == 0) {
+               omap1_clk_disable(clk);
+               omap1_clk_unuse(&api_ck.clk);
+       }
+}
+
+static int omap1_clk_enable_uart_functional(struct clk *clk)
+{
+       int ret;
+       struct uart_clk *uclk;
+
+       ret = omap1_clk_enable(clk);
+       if (ret == 0) {
+               /* Set smart idle acknowledgement mode */
+               uclk = (struct uart_clk *)clk;
+               omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8,
+                           uclk->sysc_addr);
+       }
+
+       return ret;
+}
+
+static void omap1_clk_disable_uart_functional(struct clk *clk)
+{
+       struct uart_clk *uclk;
+
+       /* Set force idle acknowledgement mode */
+       uclk = (struct uart_clk *)clk;
+       omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
+
+       omap1_clk_disable(clk);
+}
+
+static void omap1_clk_allow_idle(struct clk *clk)
+{
+       struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
+
+       if (!(clk->flags & CLOCK_IDLE_CONTROL))
+               return;
+
+       if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count))
+               arm_idlect1_mask |= 1 << iclk->idlect_shift;
+}
+
+static void omap1_clk_deny_idle(struct clk *clk)
+{
+       struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
+
+       if (!(clk->flags & CLOCK_IDLE_CONTROL))
+               return;
+
+       if (iclk->no_idle_count++ == 0)
+               arm_idlect1_mask &= ~(1 << iclk->idlect_shift);
+}
+
+static __u16 verify_ckctl_value(__u16 newval)
+{
+       /* This function checks for following limitations set
+        * by the hardware (all conditions must be true):
+        * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
+        * ARM_CK >= TC_CK
+        * DSP_CK >= TC_CK
+        * DSPMMU_CK >= TC_CK
+        *
+        * In addition following rules are enforced:
+        * LCD_CK <= TC_CK
+        * ARMPER_CK <= TC_CK
+        *
+        * However, maximum frequencies are not checked for!
+        */
+       __u8 per_exp;
+       __u8 lcd_exp;
+       __u8 arm_exp;
+       __u8 dsp_exp;
+       __u8 tc_exp;
+       __u8 dspmmu_exp;
+
+       per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
+       lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
+       arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
+       dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
+       tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
+       dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
+
+       if (dspmmu_exp < dsp_exp)
+               dspmmu_exp = dsp_exp;
+       if (dspmmu_exp > dsp_exp+1)
+               dspmmu_exp = dsp_exp+1;
+       if (tc_exp < arm_exp)
+               tc_exp = arm_exp;
+       if (tc_exp < dspmmu_exp)
+               tc_exp = dspmmu_exp;
+       if (tc_exp > lcd_exp)
+               lcd_exp = tc_exp;
+       if (tc_exp > per_exp)
+               per_exp = tc_exp;
+
+       newval &= 0xf000;
+       newval |= per_exp << CKCTL_PERDIV_OFFSET;
+       newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
+       newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
+       newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
+       newval |= tc_exp << CKCTL_TCDIV_OFFSET;
+       newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
+
+       return newval;
+}
+
+static int calc_dsor_exp(struct clk *clk, unsigned long rate)
+{
+       /* Note: If target frequency is too low, this function will return 4,
+        * which is invalid value. Caller must check for this value and act
+        * accordingly.
+        *
+        * Note: This function does not check for following limitations set
+        * by the hardware (all conditions must be true):
+        * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
+        * ARM_CK >= TC_CK
+        * DSP_CK >= TC_CK
+        * DSPMMU_CK >= TC_CK
+        */
+       unsigned long realrate;
+       struct clk * parent;
+       unsigned  dsor_exp;
+
+       if (unlikely(!(clk->flags & RATE_CKCTL)))
+               return -EINVAL;
+
+       parent = clk->parent;
+       if (unlikely(parent == 0))
+               return -EIO;
+
+       realrate = parent->rate;
+       for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
+               if (realrate <= rate)
+                       break;
+
+               realrate /= 2;
+       }
+
+       return dsor_exp;
+}
+
+static void omap1_ckctl_recalc(struct clk * clk)
+{
+       int dsor;
+
+       /* Calculate divisor encoded as 2-bit exponent */
+       dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
+
+       if (unlikely(clk->rate == clk->parent->rate / dsor))
+               return; /* No change, quick exit */
+       clk->rate = clk->parent->rate / dsor;
+
+       if (unlikely(clk->flags & RATE_PROPAGATES))
+               propagate_rate(clk);
+}
+
+static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
+{
+       int dsor;
+
+       /* Calculate divisor encoded as 2-bit exponent
+        *
+        * The clock control bits are in DSP domain,
+        * so api_ck is needed for access.
+        * Note that DSP_CKCTL virt addr = phys addr, so
+        * we must use __raw_readw() instead of omap_readw().
+        */
+       omap1_clk_use(&api_ck.clk);
+       dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
+       omap1_clk_unuse(&api_ck.clk);
+
+       if (unlikely(clk->rate == clk->parent->rate / dsor))
+               return; /* No change, quick exit */
+       clk->rate = clk->parent->rate / dsor;
+
+       if (unlikely(clk->flags & RATE_PROPAGATES))
+               propagate_rate(clk);
+}
+
+/* MPU virtual clock functions */
+static int omap1_select_table_rate(struct clk * clk, unsigned long rate)
+{
+       /* Find the highest supported frequency <= rate and switch to it */
+       struct mpu_rate * ptr;
+
+       if (clk != &virtual_ck_mpu)
+               return -EINVAL;
+
+       for (ptr = rate_table; ptr->rate; ptr++) {
+               if (ptr->xtal != ck_ref.rate)
+                       continue;
+
+               /* DPLL1 cannot be reprogrammed without risking system crash */
+               if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate)
+                       continue;
+
+               /* Can check only after xtal frequency check */
+               if (ptr->rate <= rate)
+                       break;
+       }
+
+       if (!ptr->rate)
+               return -EINVAL;
+
+       /*
+        * In most cases we should not need to reprogram DPLL.
+        * Reprogramming the DPLL is tricky, it must be done from SRAM.
+        */
+       omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
+
+       ck_dpll1.rate = ptr->pll_rate;
+       propagate_rate(&ck_dpll1);
+       return 0;
+}
+
+static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate)
+{
+       int  ret = -EINVAL;
+       int  dsor_exp;
+       __u16  regval;
+
+       if (clk->flags & RATE_CKCTL) {
+               dsor_exp = calc_dsor_exp(clk, rate);
+               if (dsor_exp > 3)
+                       dsor_exp = -EINVAL;
+               if (dsor_exp < 0)
+                       return dsor_exp;
+
+               regval = __raw_readw(DSP_CKCTL);
+               regval &= ~(3 << clk->rate_offset);
+               regval |= dsor_exp << clk->rate_offset;
+               __raw_writew(regval, DSP_CKCTL);
+               clk->rate = clk->parent->rate / (1 << dsor_exp);
+               ret = 0;
+       }
+
+       if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
+               propagate_rate(clk);
+
+       return ret;
+}
+
+static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate)
+{
+       /* Find the highest supported frequency <= rate */
+       struct mpu_rate * ptr;
+       long  highest_rate;
+
+       if (clk != &virtual_ck_mpu)
+               return -EINVAL;
+
+       highest_rate = -EINVAL;
+
+       for (ptr = rate_table; ptr->rate; ptr++) {
+               if (ptr->xtal != ck_ref.rate)
+                       continue;
+
+               highest_rate = ptr->rate;
+
+               /* Can check only after xtal frequency check */
+               if (ptr->rate <= rate)
+                       break;
+       }
+
+       return highest_rate;
+}
+
+static unsigned calc_ext_dsor(unsigned long rate)
+{
+       unsigned dsor;
+
+       /* MCLK and BCLK divisor selection is not linear:
+        * freq = 96MHz / dsor
+        *
+        * RATIO_SEL range: dsor <-> RATIO_SEL
+        * 0..6: (RATIO_SEL+2) <-> (dsor-2)
+        * 6..48:  (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
+        * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
+        * can not be used.
+        */
+       for (dsor = 2; dsor < 96; ++dsor) {
+               if ((dsor & 1) && dsor > 8)
+                       continue;
+               if (rate >= 96000000 / dsor)
+                       break;
+       }
+       return dsor;
+}
+
+/* Only needed on 1510 */
+static int omap1_set_uart_rate(struct clk * clk, unsigned long rate)
+{
+       unsigned int val;
+
+       val = omap_readl(clk->enable_reg);
+       if (rate == 12000000)
+               val &= ~(1 << clk->enable_bit);
+       else if (rate == 48000000)
+               val |= (1 << clk->enable_bit);
+       else
+               return -EINVAL;
+       omap_writel(val, clk->enable_reg);
+       clk->rate = rate;
+
+       return 0;
+}
+
+/* External clock (MCLK & BCLK) functions */
+static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate)
+{
+       unsigned dsor;
+       __u16 ratio_bits;
+
+       dsor = calc_ext_dsor(rate);
+       clk->rate = 96000000 / dsor;
+       if (dsor > 8)
+               ratio_bits = ((dsor - 8) / 2 + 6) << 2;
+       else
+               ratio_bits = (dsor - 2) << 2;
+
+       ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd;
+       omap_writew(ratio_bits, clk->enable_reg);
+
+       return 0;
+}
+
+static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate)
+{
+       return 96000000 / calc_ext_dsor(rate);
+}
+
+static void omap1_init_ext_clk(struct clk * clk)
+{
+       unsigned dsor;
+       __u16 ratio_bits;
+
+       /* Determine current rate and ensure clock is based on 96MHz APLL */
+       ratio_bits = omap_readw(clk->enable_reg) & ~1;
+       omap_writew(ratio_bits, clk->enable_reg);
+
+       ratio_bits = (ratio_bits & 0xfc) >> 2;
+       if (ratio_bits > 6)
+               dsor = (ratio_bits - 6) * 2 + 8;
+       else
+               dsor = ratio_bits + 2;
+
+       clk-> rate = 96000000 / dsor;
+}
+
+static int omap1_clk_use(struct clk *clk)
+{
+       int ret = 0;
+       if (clk->usecount++ == 0) {
+               if (likely(clk->parent)) {
+                       ret = omap1_clk_use(clk->parent);
+
+                       if (unlikely(ret != 0)) {
+                               clk->usecount--;
+                               return ret;
+                       }
+
+                       if (clk->flags & CLOCK_NO_IDLE_PARENT)
+                               if (!cpu_is_omap24xx())
+                                       omap1_clk_deny_idle(clk->parent);
+               }
+
+               ret = clk->enable(clk);
+
+               if (unlikely(ret != 0) && clk->parent) {
+                       omap1_clk_unuse(clk->parent);
+                       clk->usecount--;
+               }
+       }
+
+       return ret;
+}
+
+static void omap1_clk_unuse(struct clk *clk)
+{
+       if (clk->usecount > 0 && !(--clk->usecount)) {
+               clk->disable(clk);
+               if (likely(clk->parent)) {
+                       omap1_clk_unuse(clk->parent);
+                       if (clk->flags & CLOCK_NO_IDLE_PARENT)
+                               if (!cpu_is_omap24xx())
+                                       omap1_clk_allow_idle(clk->parent);
+               }
+       }
+}
+
+static int omap1_clk_enable(struct clk *clk)
+{
+       __u16 regval16;
+       __u32 regval32;
+
+       if (clk->flags & ALWAYS_ENABLED)
+               return 0;
+
+       if (unlikely(clk->enable_reg == 0)) {
+               printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+                      clk->name);
+               return 0;
+       }
+
+       if (clk->flags & ENABLE_REG_32BIT) {
+               if (clk->flags & VIRTUAL_IO_ADDRESS) {
+                       regval32 = __raw_readl(clk->enable_reg);
+                       regval32 |= (1 << clk->enable_bit);
+                       __raw_writel(regval32, clk->enable_reg);
+               } else {
+                       regval32 = omap_readl(clk->enable_reg);
+                       regval32 |= (1 << clk->enable_bit);
+                       omap_writel(regval32, clk->enable_reg);
+               }
+       } else {
+               if (clk->flags & VIRTUAL_IO_ADDRESS) {
+                       regval16 = __raw_readw(clk->enable_reg);
+                       regval16 |= (1 << clk->enable_bit);
+                       __raw_writew(regval16, clk->enable_reg);
+               } else {
+                       regval16 = omap_readw(clk->enable_reg);
+                       regval16 |= (1 << clk->enable_bit);
+                       omap_writew(regval16, clk->enable_reg);
+               }
+       }
+
+       return 0;
+}
+
+static void omap1_clk_disable(struct clk *clk)
+{
+       __u16 regval16;
+       __u32 regval32;
+
+       if (clk->enable_reg == 0)
+               return;
+
+       if (clk->flags & ENABLE_REG_32BIT) {
+               if (clk->flags & VIRTUAL_IO_ADDRESS) {
+                       regval32 = __raw_readl(clk->enable_reg);
+                       regval32 &= ~(1 << clk->enable_bit);
+                       __raw_writel(regval32, clk->enable_reg);
+               } else {
+                       regval32 = omap_readl(clk->enable_reg);
+                       regval32 &= ~(1 << clk->enable_bit);
+                       omap_writel(regval32, clk->enable_reg);
+               }
+       } else {
+               if (clk->flags & VIRTUAL_IO_ADDRESS) {
+                       regval16 = __raw_readw(clk->enable_reg);
+                       regval16 &= ~(1 << clk->enable_bit);
+                       __raw_writew(regval16, clk->enable_reg);
+               } else {
+                       regval16 = omap_readw(clk->enable_reg);
+                       regval16 &= ~(1 << clk->enable_bit);
+                       omap_writew(regval16, clk->enable_reg);
+               }
+       }
+}
+
+static long omap1_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       int dsor_exp;
+
+       if (clk->flags & RATE_FIXED)
+               return clk->rate;
+
+       if (clk->flags & RATE_CKCTL) {
+               dsor_exp = calc_dsor_exp(clk, rate);
+               if (dsor_exp < 0)
+                       return dsor_exp;
+               if (dsor_exp > 3)
+                       dsor_exp = 3;
+               return clk->parent->rate / (1 << dsor_exp);
+       }
+
+       if(clk->round_rate != 0)
+               return clk->round_rate(clk, rate);
+
+       return clk->rate;
+}
+
+static int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       int  ret = -EINVAL;
+       int  dsor_exp;
+       __u16  regval;
+
+       if (clk->set_rate)
+               ret = clk->set_rate(clk, rate);
+       else if (clk->flags & RATE_CKCTL) {
+               dsor_exp = calc_dsor_exp(clk, rate);
+               if (dsor_exp > 3)
+                       dsor_exp = -EINVAL;
+               if (dsor_exp < 0)
+                       return dsor_exp;
+
+               regval = omap_readw(ARM_CKCTL);
+               regval &= ~(3 << clk->rate_offset);
+               regval |= dsor_exp << clk->rate_offset;
+               regval = verify_ckctl_value(regval);
+               omap_writew(regval, ARM_CKCTL);
+               clk->rate = clk->parent->rate / (1 << dsor_exp);
+               ret = 0;
+       }
+
+       if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
+               propagate_rate(clk);
+
+       return ret;
+}
+
+/*-------------------------------------------------------------------------
+ * Omap1 clock reset and init functions
+ *-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+/*
+ * Resets some clocks that may be left on from bootloader,
+ * but leaves serial clocks on. See also omap_late_clk_reset().
+ */
+static inline void omap1_early_clk_reset(void)
+{
+       //omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
+}
+
+static int __init omap1_late_clk_reset(void)
+{
+       /* Turn off all unused clocks */
+       struct clk *p;
+       __u32 regval32;
+
+       /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
+       regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
+       omap_writew(regval32, SOFT_REQ_REG);
+       omap_writew(0, SOFT_REQ_REG2);
+
+       list_for_each_entry(p, &clocks, node) {
+               if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) ||
+                       p->enable_reg == 0)
+                       continue;
+
+               /* Clocks in the DSP domain need api_ck. Just assume bootloader
+                * has not enabled any DSP clocks */
+               if ((u32)p->enable_reg == DSP_IDLECT2) {
+                       printk(KERN_INFO "Skipping reset check for DSP domain "
+                              "clock \"%s\"\n", p->name);
+                       continue;
+               }
+
+               /* Is the clock already disabled? */
+               if (p->flags & ENABLE_REG_32BIT) {
+                       if (p->flags & VIRTUAL_IO_ADDRESS)
+                               regval32 = __raw_readl(p->enable_reg);
+                       else
+                               regval32 = omap_readl(p->enable_reg);
+               } else {
+                       if (p->flags & VIRTUAL_IO_ADDRESS)
+                               regval32 = __raw_readw(p->enable_reg);
+                       else
+                               regval32 = omap_readw(p->enable_reg);
+               }
+
+               if ((regval32 & (1 << p->enable_bit)) == 0)
+                       continue;
+
+               /* FIXME: This clock seems to be necessary but no-one
+                * has asked for its activation. */
+               if (p == &tc2_ck         // FIX: pm.c (SRAM), CCP, Camera
+                   || p == &ck_dpll1out.clk // FIX: SoSSI, SSR
+                   || p == &arm_gpio_ck // FIX: GPIO code for 1510
+                   ) {
+                       printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
+                              p->name);
+                       continue;
+               }
+
+               printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name);
+               p->disable(p);
+               printk(" done\n");
+       }
+
+       return 0;
+}
+late_initcall(omap1_late_clk_reset);
+
+#else
+#define omap1_early_clk_reset()        {}
+#endif
+
+static struct clk_functions omap1_clk_functions = {
+       .clk_use                = omap1_clk_use,
+       .clk_unuse              = omap1_clk_unuse,
+       .clk_round_rate         = omap1_clk_round_rate,
+       .clk_set_rate           = omap1_clk_set_rate,
+};
+
+int __init omap1_clk_init(void)
+{
+       struct clk ** clkp;
+       const struct omap_clock_config *info;
+       int crystal_type = 0; /* Default 12 MHz */
+
+       omap1_early_clk_reset();
+       clk_init(&omap1_clk_functions);
+
+       /* By default all idlect1 clocks are allowed to idle */
+       arm_idlect1_mask = ~0;
+
+       for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
+               if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) {
+                       clk_register(*clkp);
+                       continue;
+               }
+
+               if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) {
+                       clk_register(*clkp);
+                       continue;
+               }
+
+               if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) {
+                       clk_register(*clkp);
+                       continue;
+               }
+       }
+
+       info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
+       if (info != NULL) {
+               if (!cpu_is_omap1510())
+                       crystal_type = info->system_clock_type;
+       }
+
+#if defined(CONFIG_ARCH_OMAP730)
+       ck_ref.rate = 13000000;
+#elif defined(CONFIG_ARCH_OMAP16XX)
+       if (crystal_type == 2)
+               ck_ref.rate = 19200000;
+#endif
+
+       printk("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n",
+              omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
+              omap_readw(ARM_CKCTL));
+
+       /* We want to be in syncronous scalable mode */
+       omap_writew(0x1000, ARM_SYSST);
+
+#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
+       /* Use values set by bootloader. Determine PLL rate and recalculate
+        * dependent clocks as if kernel had changed PLL or divisors.
+        */
+       {
+               unsigned pll_ctl_val = omap_readw(DPLL_CTL);
+
+               ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */
+               if (pll_ctl_val & 0x10) {
+                       /* PLL enabled, apply multiplier and divisor */
+                       if (pll_ctl_val & 0xf80)
+                               ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7;
+                       ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1;
+               } else {
+                       /* PLL disabled, apply bypass divisor */
+                       switch (pll_ctl_val & 0xc) {
+                       case 0:
+                               break;
+                       case 0x4:
+                               ck_dpll1.rate /= 2;
+                               break;
+                       default:
+                               ck_dpll1.rate /= 4;
+                               break;
+                       }
+               }
+       }
+       propagate_rate(&ck_dpll1);
+#else
+       /* Find the highest supported frequency and enable it */
+       if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
+               printk(KERN_ERR "System frequencies not set. Check your config.\n");
+               /* Guess sane values (60MHz) */
+               omap_writew(0x2290, DPLL_CTL);
+               omap_writew(0x1005, ARM_CKCTL);
+               ck_dpll1.rate = 60000000;
+               propagate_rate(&ck_dpll1);
+       }
+#endif
+       /* Cache rates for clocks connected to ck_ref (not dpll1) */
+       propagate_rate(&ck_ref);
+       printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
+               "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
+              ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
+              ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+              arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
+
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+       /* Select slicer output as OMAP input clock */
+       omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
+#endif
+
+       /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
+       omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
+
+       /* Put DSP/MPUI into reset until needed */
+       omap_writew(0, ARM_RSTCT1);
+       omap_writew(1, ARM_RSTCT2);
+       omap_writew(0x400, ARM_IDLECT1);
+
+       /*
+        * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
+        * of the ARM_IDLECT2 register must be set to zero. The power-on
+        * default value of this bit is one.
+        */
+       omap_writew(0x0000, ARM_IDLECT2);       /* Turn LCD clock off also */
+
+       /*
+        * Only enable those clocks we will need, let the drivers
+        * enable other clocks as necessary
+        */
+       clk_use(&armper_ck.clk);
+       clk_use(&armxor_ck.clk);
+       clk_use(&armtim_ck.clk); /* This should be done by timer code */
+
+       if (cpu_is_omap1510())
+               clk_enable(&arm_gpio_ck);
+
+       return 0;
+}
+
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
new file mode 100644 (file)
index 0000000..f3bdfb5
--- /dev/null
@@ -0,0 +1,768 @@
+/*
+ *  linux/arch/arm/mach-omap1/clock.h
+ *
+ *  Copyright (C) 2004 - 2005 Nokia corporation
+ *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *  Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H
+#define __ARCH_ARM_MACH_OMAP1_CLOCK_H
+
+static int omap1_clk_enable(struct clk * clk);
+static void omap1_clk_disable(struct clk * clk);
+static void omap1_ckctl_recalc(struct clk * clk);
+static void omap1_watchdog_recalc(struct clk * clk);
+static void omap1_ckctl_recalc_dsp_domain(struct clk * clk);
+static int omap1_clk_enable_dsp_domain(struct clk * clk);
+static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate);
+static void omap1_clk_disable_dsp_domain(struct clk * clk);
+static int omap1_set_uart_rate(struct clk * clk, unsigned long rate);
+static void omap1_uart_recalc(struct clk * clk);
+static int omap1_clk_enable_uart_functional(struct clk * clk);
+static void omap1_clk_disable_uart_functional(struct clk * clk);
+static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate);
+static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate);
+static void omap1_init_ext_clk(struct clk * clk);
+static int omap1_select_table_rate(struct clk * clk, unsigned long rate);
+static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate);
+static int omap1_clk_use(struct clk *clk);
+static void omap1_clk_unuse(struct clk *clk);
+
+struct mpu_rate {
+       unsigned long           rate;
+       unsigned long           xtal;
+       unsigned long           pll_rate;
+       __u16                   ckctl_val;
+       __u16                   dpllctl_val;
+};
+
+struct uart_clk {
+       struct clk      clk;
+       unsigned long   sysc_addr;
+};
+
+/* Provide a method for preventing idling some ARM IDLECT clocks */
+struct arm_idlect1_clk {
+       struct clk      clk;
+       unsigned long   no_idle_count;
+       __u8            idlect_shift;
+};
+
+/* ARM_CKCTL bit shifts */
+#define CKCTL_PERDIV_OFFSET    0
+#define CKCTL_LCDDIV_OFFSET    2
+#define CKCTL_ARMDIV_OFFSET    4
+#define CKCTL_DSPDIV_OFFSET    6
+#define CKCTL_TCDIV_OFFSET     8
+#define CKCTL_DSPMMUDIV_OFFSET 10
+/*#define ARM_TIMXO            12*/
+#define EN_DSPCK               13
+/*#define ARM_INTHCK_SEL       14*/ /* Divide-by-2 for mpu inth_ck */
+/* DSP_CKCTL bit shifts */
+#define CKCTL_DSPPERDIV_OFFSET 0
+
+/* ARM_IDLECT2 bit shifts */
+#define EN_WDTCK       0
+#define EN_XORPCK      1
+#define EN_PERCK       2
+#define EN_LCDCK       3
+#define EN_LBCK                4 /* Not on 1610/1710 */
+/*#define EN_HSABCK    5*/
+#define EN_APICK       6
+#define EN_TIMCK       7
+#define DMACK_REQ      8
+#define EN_GPIOCK      9 /* Not on 1610/1710 */
+/*#define EN_LBFREECK  10*/
+#define EN_CKOUT_ARM   11
+
+/* ARM_IDLECT3 bit shifts */
+#define EN_OCPI_CK     0
+#define EN_TC1_CK      2
+#define EN_TC2_CK      4
+
+/* DSP_IDLECT2 bit shifts (0,1,2 are same as for ARM_IDLECT2) */
+#define EN_DSPTIMCK    5
+
+/* Various register defines for clock controls scattered around OMAP chip */
+#define USB_MCLK_EN_BIT                4       /* In ULPD_CLKC_CTRL */
+#define USB_HOST_HHC_UHOST_EN  9       /* In MOD_CONF_CTRL_0 */
+#define SWD_ULPD_PLL_CLK_REQ   1       /* In SWD_CLK_DIV_CTRL_SEL */
+#define COM_ULPD_PLL_CLK_REQ   1       /* In COM_CLK_DIV_CTRL_SEL */
+#define SWD_CLK_DIV_CTRL_SEL   0xfffe0874
+#define COM_CLK_DIV_CTRL_SEL   0xfffe0878
+#define SOFT_REQ_REG           0xfffe0834
+#define SOFT_REQ_REG2          0xfffe0880
+
+/*-------------------------------------------------------------------------
+ * Omap1 MPU rate table
+ *-------------------------------------------------------------------------*/
+static struct mpu_rate rate_table[] = {
+       /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL
+        * NOTE: Comment order here is different from bits in CKCTL value:
+        * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv
+        */
+#if defined(CONFIG_OMAP_ARM_216MHZ)
+       { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_195MHZ)
+       { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_192MHZ)
+       { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */
+       { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */
+       {  96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */
+       {  48000000, 12000000, 192000000, 0x0baf, 0x2810 }, /* 4/4/4/8/8/8 */
+       {  24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_182MHZ)
+       { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_168MHZ)
+       { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_150MHZ)
+       { 150000000, 12000000, 150000000, 0x010a, 0x2cb0 }, /* 1/1/1/2/4/4 */
+#endif
+#if defined(CONFIG_OMAP_ARM_120MHZ)
+       { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */
+#endif
+#if defined(CONFIG_OMAP_ARM_96MHZ)
+       {  96000000, 12000000,  96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */
+#endif
+#if defined(CONFIG_OMAP_ARM_60MHZ)
+       {  60000000, 12000000,  60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */
+#endif
+#if defined(CONFIG_OMAP_ARM_30MHZ)
+       {  30000000, 12000000,  60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */
+#endif
+       { 0, 0, 0, 0, 0 },
+};
+
+/*-------------------------------------------------------------------------
+ * Omap1 clocks
+ *-------------------------------------------------------------------------*/
+
+static struct clk ck_ref = {
+       .name           = "ck_ref",
+       .rate           = 12000000,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         ALWAYS_ENABLED,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk ck_dpll1 = {
+       .name           = "ck_dpll1",
+       .parent         = &ck_ref,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         RATE_PROPAGATES | ALWAYS_ENABLED,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct arm_idlect1_clk ck_dpll1out = {
+       .clk = {
+               .name           = "ck_dpll1out",
+               .parent         = &ck_dpll1,
+               .flags          = CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_CKOUT_ARM,
+               .recalc         = &followparent_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 12,
+};
+
+static struct clk arm_ck = {
+       .name           = "arm_ck",
+       .parent         = &ck_dpll1,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .rate_offset    = CKCTL_ARMDIV_OFFSET,
+       .recalc         = &omap1_ckctl_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct arm_idlect1_clk armper_ck = {
+       .clk = {
+               .name           = "armper_ck",
+               .parent         = &ck_dpll1,
+               .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                                 RATE_CKCTL | CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_PERCK,
+               .rate_offset    = CKCTL_PERDIV_OFFSET,
+               .recalc         = &omap1_ckctl_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 2,
+};
+
+static struct clk arm_gpio_ck = {
+       .name           = "arm_gpio_ck",
+       .parent         = &ck_dpll1,
+       .flags          = CLOCK_IN_OMAP1510,
+       .enable_reg     = (void __iomem *)ARM_IDLECT2,
+       .enable_bit     = EN_GPIOCK,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct arm_idlect1_clk armxor_ck = {
+       .clk = {
+               .name           = "armxor_ck",
+               .parent         = &ck_ref,
+               .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                                 CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_XORPCK,
+               .recalc         = &followparent_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 1,
+};
+
+static struct arm_idlect1_clk armtim_ck = {
+       .clk = {
+               .name           = "armtim_ck",
+               .parent         = &ck_ref,
+               .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                                 CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_TIMCK,
+               .recalc         = &followparent_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 9,
+};
+
+static struct arm_idlect1_clk armwdt_ck = {
+       .clk = {
+               .name           = "armwdt_ck",
+               .parent         = &ck_ref,
+               .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                                 CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_WDTCK,
+               .recalc         = &omap1_watchdog_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 0,
+};
+
+static struct clk arminth_ck16xx = {
+       .name           = "arminth_ck",
+       .parent         = &arm_ck,
+       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
+       .recalc         = &followparent_recalc,
+       /* Note: On 16xx the frequency can be divided by 2 by programming
+        * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
+        *
+        * 1510 version is in TC clocks.
+        */
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk dsp_ck = {
+       .name           = "dsp_ck",
+       .parent         = &ck_dpll1,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         RATE_CKCTL,
+       .enable_reg     = (void __iomem *)ARM_CKCTL,
+       .enable_bit     = EN_DSPCK,
+       .rate_offset    = CKCTL_DSPDIV_OFFSET,
+       .recalc         = &omap1_ckctl_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk dspmmu_ck = {
+       .name           = "dspmmu_ck",
+       .parent         = &ck_dpll1,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         RATE_CKCTL | ALWAYS_ENABLED,
+       .rate_offset    = CKCTL_DSPMMUDIV_OFFSET,
+       .recalc         = &omap1_ckctl_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk dspper_ck = {
+       .name           = "dspper_ck",
+       .parent         = &ck_dpll1,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         RATE_CKCTL | VIRTUAL_IO_ADDRESS,
+       .enable_reg     = (void __iomem *)DSP_IDLECT2,
+       .enable_bit     = EN_PERCK,
+       .rate_offset    = CKCTL_PERDIV_OFFSET,
+       .recalc         = &omap1_ckctl_recalc_dsp_domain,
+       .set_rate       = &omap1_clk_set_rate_dsp_domain,
+       .enable         = &omap1_clk_enable_dsp_domain,
+       .disable        = &omap1_clk_disable_dsp_domain,
+};
+
+static struct clk dspxor_ck = {
+       .name           = "dspxor_ck",
+       .parent         = &ck_ref,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         VIRTUAL_IO_ADDRESS,
+       .enable_reg     = (void __iomem *)DSP_IDLECT2,
+       .enable_bit     = EN_XORPCK,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable_dsp_domain,
+       .disable        = &omap1_clk_disable_dsp_domain,
+};
+
+static struct clk dsptim_ck = {
+       .name           = "dsptim_ck",
+       .parent         = &ck_ref,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         VIRTUAL_IO_ADDRESS,
+       .enable_reg     = (void __iomem *)DSP_IDLECT2,
+       .enable_bit     = EN_DSPTIMCK,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable_dsp_domain,
+       .disable        = &omap1_clk_disable_dsp_domain,
+};
+
+/* Tie ARM_IDLECT1:IDLIF_ARM to this logical clock structure */
+static struct arm_idlect1_clk tc_ck = {
+       .clk = {
+               .name           = "tc_ck",
+               .parent         = &ck_dpll1,
+               .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                                 CLOCK_IN_OMAP730 | RATE_CKCTL |
+                                 RATE_PROPAGATES | ALWAYS_ENABLED |
+                                 CLOCK_IDLE_CONTROL,
+               .rate_offset    = CKCTL_TCDIV_OFFSET,
+               .recalc         = &omap1_ckctl_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 6,
+};
+
+static struct clk arminth_ck1510 = {
+       .name           = "arminth_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+       .recalc         = &followparent_recalc,
+       /* Note: On 1510 the frequency follows TC_CK
+        *
+        * 16xx version is in MPU clocks.
+        */
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk tipb_ck = {
+       /* No-idle controlled by "tc_ck" */
+       .name           = "tibp_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk l3_ocpi_ck = {
+       /* No-idle controlled by "tc_ck" */
+       .name           = "l3_ocpi_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP16XX,
+       .enable_reg     = (void __iomem *)ARM_IDLECT3,
+       .enable_bit     = EN_OCPI_CK,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk tc1_ck = {
+       .name           = "tc1_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP16XX,
+       .enable_reg     = (void __iomem *)ARM_IDLECT3,
+       .enable_bit     = EN_TC1_CK,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk tc2_ck = {
+       .name           = "tc2_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP16XX,
+       .enable_reg     = (void __iomem *)ARM_IDLECT3,
+       .enable_bit     = EN_TC2_CK,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk dma_ck = {
+       /* No-idle controlled by "tc_ck" */
+       .name           = "dma_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         ALWAYS_ENABLED,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk dma_lcdfree_ck = {
+       .name           = "dma_lcdfree_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct arm_idlect1_clk api_ck = {
+       .clk = {
+               .name           = "api_ck",
+               .parent         = &tc_ck.clk,
+               .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                                 CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_APICK,
+               .recalc         = &followparent_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 8,
+};
+
+static struct arm_idlect1_clk lb_ck = {
+       .clk = {
+               .name           = "lb_ck",
+               .parent         = &tc_ck.clk,
+               .flags          = CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_LBCK,
+               .recalc         = &followparent_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 4,
+};
+
+static struct clk rhea1_ck = {
+       .name           = "rhea1_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk rhea2_ck = {
+       .name           = "rhea2_ck",
+       .parent         = &tc_ck.clk,
+       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
+       .recalc         = &followparent_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk lcd_ck_16xx = {
+       .name           = "lcd_ck",
+       .parent         = &ck_dpll1,
+       .flags          = CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | RATE_CKCTL,
+       .enable_reg     = (void __iomem *)ARM_IDLECT2,
+       .enable_bit     = EN_LCDCK,
+       .rate_offset    = CKCTL_LCDDIV_OFFSET,
+       .recalc         = &omap1_ckctl_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct arm_idlect1_clk lcd_ck_1510 = {
+       .clk = {
+               .name           = "lcd_ck",
+               .parent         = &ck_dpll1,
+               .flags          = CLOCK_IN_OMAP1510 | RATE_CKCTL |
+                                 CLOCK_IDLE_CONTROL,
+               .enable_reg     = (void __iomem *)ARM_IDLECT2,
+               .enable_bit     = EN_LCDCK,
+               .rate_offset    = CKCTL_LCDDIV_OFFSET,
+               .recalc         = &omap1_ckctl_recalc,
+               .enable         = &omap1_clk_enable,
+               .disable        = &omap1_clk_disable,
+       },
+       .idlect_shift   = 3,
+};
+
+static struct clk uart1_1510 = {
+       .name           = "uart1_ck",
+       /* Direct from ULPD, no real parent */
+       .parent         = &armper_ck.clk,
+       .rate           = 12000000,
+       .flags          = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
+                         ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+       .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+       .enable_bit     = 29,   /* Chooses between 12MHz and 48MHz */
+       .set_rate       = &omap1_set_uart_rate,
+       .recalc         = &omap1_uart_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct uart_clk uart1_16xx = {
+       .clk    = {
+               .name           = "uart1_ck",
+               /* Direct from ULPD, no real parent */
+               .parent         = &armper_ck.clk,
+               .rate           = 48000000,
+               .flags          = CLOCK_IN_OMAP16XX | RATE_FIXED |
+                                 ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+               .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+               .enable_bit     = 29,
+               .enable         = &omap1_clk_enable_uart_functional,
+               .disable        = &omap1_clk_disable_uart_functional,
+       },
+       .sysc_addr      = 0xfffb0054,
+};
+
+static struct clk uart2_ck = {
+       .name           = "uart2_ck",
+       /* Direct from ULPD, no real parent */
+       .parent         = &armper_ck.clk,
+       .rate           = 12000000,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         ENABLE_REG_32BIT | ALWAYS_ENABLED |
+                         CLOCK_NO_IDLE_PARENT,
+       .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+       .enable_bit     = 30,   /* Chooses between 12MHz and 48MHz */
+       .set_rate       = &omap1_set_uart_rate,
+       .recalc         = &omap1_uart_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk uart3_1510 = {
+       .name           = "uart3_ck",
+       /* Direct from ULPD, no real parent */
+       .parent         = &armper_ck.clk,
+       .rate           = 12000000,
+       .flags          = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
+                         ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+       .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+       .enable_bit     = 31,   /* Chooses between 12MHz and 48MHz */
+       .set_rate       = &omap1_set_uart_rate,
+       .recalc         = &omap1_uart_recalc,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct uart_clk uart3_16xx = {
+       .clk    = {
+               .name           = "uart3_ck",
+               /* Direct from ULPD, no real parent */
+               .parent         = &armper_ck.clk,
+               .rate           = 48000000,
+               .flags          = CLOCK_IN_OMAP16XX | RATE_FIXED |
+                                 ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+               .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+               .enable_bit     = 31,
+               .enable         = &omap1_clk_enable_uart_functional,
+               .disable        = &omap1_clk_disable_uart_functional,
+       },
+       .sysc_addr      = 0xfffb9854,
+};
+
+static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
+       .name           = "usb_clko",
+       /* Direct from ULPD, no parent */
+       .rate           = 6000000,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         RATE_FIXED | ENABLE_REG_32BIT,
+       .enable_reg     = (void __iomem *)ULPD_CLOCK_CTRL,
+       .enable_bit     = USB_MCLK_EN_BIT,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk usb_hhc_ck1510 = {
+       .name           = "usb_hhc_ck",
+       /* Direct from ULPD, no parent */
+       .rate           = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
+       .flags          = CLOCK_IN_OMAP1510 |
+                         RATE_FIXED | ENABLE_REG_32BIT,
+       .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+       .enable_bit     = USB_HOST_HHC_UHOST_EN,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk usb_hhc_ck16xx = {
+       .name           = "usb_hhc_ck",
+       /* Direct from ULPD, no parent */
+       .rate           = 48000000,
+       /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
+       .flags          = CLOCK_IN_OMAP16XX |
+                         RATE_FIXED | ENABLE_REG_32BIT,
+       .enable_reg     = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
+       .enable_bit     = 8 /* UHOST_EN */,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk usb_dc_ck = {
+       .name           = "usb_dc_ck",
+       /* Direct from ULPD, no parent */
+       .rate           = 48000000,
+       .flags          = CLOCK_IN_OMAP16XX | RATE_FIXED,
+       .enable_reg     = (void __iomem *)SOFT_REQ_REG,
+       .enable_bit     = 4,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk mclk_1510 = {
+       .name           = "mclk",
+       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+       .rate           = 12000000,
+       .flags          = CLOCK_IN_OMAP1510 | RATE_FIXED,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk mclk_16xx = {
+       .name           = "mclk",
+       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+       .flags          = CLOCK_IN_OMAP16XX,
+       .enable_reg     = (void __iomem *)COM_CLK_DIV_CTRL_SEL,
+       .enable_bit     = COM_ULPD_PLL_CLK_REQ,
+       .set_rate       = &omap1_set_ext_clk_rate,
+       .round_rate     = &omap1_round_ext_clk_rate,
+       .init           = &omap1_init_ext_clk,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk bclk_1510 = {
+       .name           = "bclk",
+       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+       .rate           = 12000000,
+       .flags          = CLOCK_IN_OMAP1510 | RATE_FIXED,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk bclk_16xx = {
+       .name           = "bclk",
+       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+       .flags          = CLOCK_IN_OMAP16XX,
+       .enable_reg     = (void __iomem *)SWD_CLK_DIV_CTRL_SEL,
+       .enable_bit     = SWD_ULPD_PLL_CLK_REQ,
+       .set_rate       = &omap1_set_ext_clk_rate,
+       .round_rate     = &omap1_round_ext_clk_rate,
+       .init           = &omap1_init_ext_clk,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk mmc1_ck = {
+       .name           = "mmc1_ck",
+       /* Functional clock is direct from ULPD, interface clock is ARMPER */
+       .parent         = &armper_ck.clk,
+       .rate           = 48000000,
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+       .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+       .enable_bit     = 23,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk mmc2_ck = {
+       .name           = "mmc2_ck",
+       /* Functional clock is direct from ULPD, interface clock is ARMPER */
+       .parent         = &armper_ck.clk,
+       .rate           = 48000000,
+       .flags          = CLOCK_IN_OMAP16XX |
+                         RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+       .enable_reg     = (void __iomem *)MOD_CONF_CTRL_0,
+       .enable_bit     = 20,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk virtual_ck_mpu = {
+       .name           = "mpu",
+       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+                         VIRTUAL_CLOCK | ALWAYS_ENABLED,
+       .parent         = &arm_ck, /* Is smarter alias for */
+       .recalc         = &followparent_recalc,
+       .set_rate       = &omap1_select_table_rate,
+       .round_rate     = &omap1_round_to_table_rate,
+       .enable         = &omap1_clk_enable,
+       .disable        = &omap1_clk_disable,
+};
+
+static struct clk * onchip_clks[] = {
+       /* non-ULPD clocks */
+       &ck_ref,
+       &ck_dpll1,
+       /* CK_GEN1 clocks */
+       &ck_dpll1out.clk,
+       &arm_ck,
+       &armper_ck.clk,
+       &arm_gpio_ck,
+       &armxor_ck.clk,
+       &armtim_ck.clk,
+       &armwdt_ck.clk,
+       &arminth_ck1510,  &arminth_ck16xx,
+       /* CK_GEN2 clocks */
+       &dsp_ck,
+       &dspmmu_ck,
+       &dspper_ck,
+       &dspxor_ck,
+       &dsptim_ck,
+       /* CK_GEN3 clocks */
+       &tc_ck.clk,
+       &tipb_ck,
+       &l3_ocpi_ck,
+       &tc1_ck,
+       &tc2_ck,
+       &dma_ck,
+       &dma_lcdfree_ck,
+       &api_ck.clk,
+       &lb_ck.clk,
+       &rhea1_ck,
+       &rhea2_ck,
+       &lcd_ck_16xx,
+       &lcd_ck_1510.clk,
+       /* ULPD clocks */
+       &uart1_1510,
+       &uart1_16xx.clk,
+       &uart2_ck,
+       &uart3_1510,
+       &uart3_16xx.clk,
+       &usb_clko,
+       &usb_hhc_ck1510, &usb_hhc_ck16xx,
+       &usb_dc_ck,
+       &mclk_1510,  &mclk_16xx,
+       &bclk_1510,  &bclk_16xx,
+       &mmc1_ck,
+       &mmc2_ck,
+       /* Virtual clocks */
+       &virtual_ck_mpu,
+};
+
+#endif
index 3c5d901efeaa88d94b17be82c029c3ba082dab31..ecbc47514adc6b4f51f148750d44d6d4778618a7 100644 (file)
 #include <asm/arch/mux.h>
 #include <asm/arch/gpio.h>
 
-
-static void omap_nop_release(struct device *dev)
-{
-        /* Nothing */
-}
-
-/*-------------------------------------------------------------------------*/
-
-#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
-
-#define        OMAP_I2C_BASE           0xfffb3800
-
-static struct resource i2c_resources[] = {
-       {
-               .start          = OMAP_I2C_BASE,
-               .end            = OMAP_I2C_BASE + 0x3f,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = INT_I2C,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-/* DMA not used; works around erratum writing to non-empty i2c fifo */
-
-static struct platform_device omap_i2c_device = {
-        .name           = "i2c_omap",
-        .id             = -1,
-        .dev = {
-                .release        = omap_nop_release,
-        },
-       .num_resources  = ARRAY_SIZE(i2c_resources),
-       .resource       = i2c_resources,
-};
-
-static void omap_init_i2c(void)
-{
-       /* FIXME define and use a boot tag, in case of boards that
-        * either don't wire up I2C, or chips that mux it differently...
-        * it can include clocking and address info, maybe more.
-        */
-       omap_cfg_reg(I2C_SCL);
-       omap_cfg_reg(I2C_SDA);
-
-       (void) platform_device_register(&omap_i2c_device);
-}
-#else
-static inline void omap_init_i2c(void) {}
-#endif
+extern void omap_nop_release(struct device *dev);
 
 /*-------------------------------------------------------------------------*/
 
@@ -110,137 +61,6 @@ static inline void omap_init_irda(void) {}
 
 /*-------------------------------------------------------------------------*/
 
-#if    defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
-
-#define        OMAP_MMC1_BASE          0xfffb7800
-#define        OMAP_MMC2_BASE          0xfffb7c00      /* omap16xx only */
-
-static struct omap_mmc_conf mmc1_conf;
-
-static u64 mmc1_dmamask = 0xffffffff;
-
-static struct resource mmc1_resources[] = {
-       {
-               .start          = IO_ADDRESS(OMAP_MMC1_BASE),
-               .end            = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = INT_MMC,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device mmc_omap_device1 = {
-       .name           = "mmci-omap",
-       .id             = 1,
-       .dev = {
-               .release        = omap_nop_release,
-               .dma_mask       = &mmc1_dmamask,
-               .platform_data  = &mmc1_conf,
-       },
-       .num_resources  = ARRAY_SIZE(mmc1_resources),
-       .resource       = mmc1_resources,
-};
-
-#ifdef CONFIG_ARCH_OMAP16XX
-
-static struct omap_mmc_conf mmc2_conf;
-
-static u64 mmc2_dmamask = 0xffffffff;
-
-static struct resource mmc2_resources[] = {
-       {
-               .start          = IO_ADDRESS(OMAP_MMC2_BASE),
-               .end            = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = INT_1610_MMC2,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device mmc_omap_device2 = {
-       .name           = "mmci-omap",
-       .id             = 2,
-       .dev = {
-               .release        = omap_nop_release,
-               .dma_mask       = &mmc2_dmamask,
-               .platform_data  = &mmc2_conf,
-       },
-       .num_resources  = ARRAY_SIZE(mmc2_resources),
-       .resource       = mmc2_resources,
-};
-#endif
-
-static void __init omap_init_mmc(void)
-{
-       const struct omap_mmc_config    *mmc_conf;
-       const struct omap_mmc_conf      *mmc;
-
-       /* NOTE:  assumes MMC was never (wrongly) enabled */
-       mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
-       if (!mmc_conf)
-               return;
-
-       /* block 1 is always available and has just one pinout option */
-       mmc = &mmc_conf->mmc[0];
-       if (mmc->enabled) {
-               omap_cfg_reg(MMC_CMD);
-               omap_cfg_reg(MMC_CLK);
-               omap_cfg_reg(MMC_DAT0);
-               if (cpu_is_omap1710()) {
-                     omap_cfg_reg(M15_1710_MMC_CLKI);
-                     omap_cfg_reg(P19_1710_MMC_CMDDIR);
-                     omap_cfg_reg(P20_1710_MMC_DATDIR0);
-               }
-               if (mmc->wire4) {
-                       omap_cfg_reg(MMC_DAT1);
-                       /* NOTE:  DAT2 can be on W10 (here) or M15 */
-                       if (!mmc->nomux)
-                               omap_cfg_reg(MMC_DAT2);
-                       omap_cfg_reg(MMC_DAT3);
-               }
-               mmc1_conf = *mmc;
-               (void) platform_device_register(&mmc_omap_device1);
-       }
-
-#ifdef CONFIG_ARCH_OMAP16XX
-       /* block 2 is on newer chips, and has many pinout options */
-       mmc = &mmc_conf->mmc[1];
-       if (mmc->enabled) {
-               if (!mmc->nomux) {
-                       omap_cfg_reg(Y8_1610_MMC2_CMD);
-                       omap_cfg_reg(Y10_1610_MMC2_CLK);
-                       omap_cfg_reg(R18_1610_MMC2_CLKIN);
-                       omap_cfg_reg(W8_1610_MMC2_DAT0);
-                       if (mmc->wire4) {
-                               omap_cfg_reg(V8_1610_MMC2_DAT1);
-                               omap_cfg_reg(W15_1610_MMC2_DAT2);
-                               omap_cfg_reg(R10_1610_MMC2_DAT3);
-                       }
-
-                       /* These are needed for the level shifter */
-                       omap_cfg_reg(V9_1610_MMC2_CMDDIR);
-                       omap_cfg_reg(V5_1610_MMC2_DATDIR0);
-                       omap_cfg_reg(W19_1610_MMC2_DATDIR1);
-               }
-
-               /* Feedback clock must be set on OMAP-1710 MMC2 */
-               if (cpu_is_omap1710())
-                       omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
-                                    MOD_CONF_CTRL_1);
-               mmc2_conf = *mmc;
-               (void) platform_device_register(&mmc_omap_device2);
-       }
-#endif
-       return;
-}
-#else
-static inline void omap_init_mmc(void) {}
-#endif
-
 #if    defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC)
 
 #define        OMAP_RTC_BASE           0xfffb4800
@@ -279,38 +99,6 @@ static void omap_init_rtc(void)
 static inline void omap_init_rtc(void) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
-#if    defined(CONFIG_OMAP16XX_WATCHDOG) || defined(CONFIG_OMAP16XX_WATCHDOG_MODULE)
-
-#define        OMAP_WDT_BASE           0xfffeb000
-
-static struct resource wdt_resources[] = {
-       {
-               .start          = OMAP_WDT_BASE,
-               .end            = OMAP_WDT_BASE + 0x4f,
-               .flags          = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device omap_wdt_device = {
-       .name      = "omap1610_wdt",
-       .id          = -1,
-       .dev = {
-               .release        = omap_nop_release,
-       },
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-       .resource       = wdt_resources,
-};
-
-static void omap_init_wdt(void)
-{
-       (void) platform_device_register(&omap_wdt_device);
-}
-#else
-static inline void omap_init_wdt(void) {}
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -334,18 +122,15 @@ static inline void omap_init_wdt(void) {}
  * may be handled by the boot loader, and drivers should expect it will
  * normally have been done by the time they're probed.
  */
-static int __init omap_init_devices(void)
+static int __init omap1_init_devices(void)
 {
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
-       omap_init_i2c();
        omap_init_irda();
-       omap_init_mmc();
        omap_init_rtc();
-       omap_init_wdt();
 
        return 0;
 }
-arch_initcall(omap_init_devices);
+arch_initcall(omap1_init_devices);
 
index 986c3b7e09bbf464d35052febf3d62e5c0842d09..5c637c0483688d9ef1a6172ad6a5fd437ba3cad2 100644 (file)
 
 #include <asm/io.h>
 
+#define OMAP_DIE_ID_0          0xfffe1800
+#define OMAP_DIE_ID_1          0xfffe1804
+#define OMAP_PRODUCTION_ID_0   0xfffe2000
+#define OMAP_PRODUCTION_ID_1   0xfffe2004
+#define OMAP32_ID_0            0xfffed400
+#define OMAP32_ID_1            0xfffed404
+
 struct omap_id {
        u16     jtag_id;        /* Used to determine OMAP type */
        u8      die_rev;        /* Processor revision */
@@ -27,6 +34,7 @@ struct omap_id {
 
 /* Register values to detect the OMAP version */
 static struct omap_id omap_ids[] __initdata = {
+       { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000},
        { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
        { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
        { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
@@ -164,6 +172,7 @@ void __init omap_check_revision(void)
        case 0x07:
                system_rev |= 0x07;
                break;
+       case 0x03:
        case 0x15:
                system_rev |= 0x15;
                break;
index 79fb86535ebcb122baca48d47ee14a867c1706ae..a7a19f75b9e1ad119434cb001c96d5c4a79b28f2 100644 (file)
 
 #include <asm/mach/map.h>
 #include <asm/io.h>
+#include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
 
-extern int clk_init(void);
+extern int omap1_clk_init(void);
 extern void omap_check_revision(void);
 extern void omap_sram_init(void);
 
@@ -50,7 +51,7 @@ static struct map_desc omap730_io_desc[] __initdata = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 static struct map_desc omap1510_io_desc[] __initdata = {
        {
                .virtual        = OMAP1510_DSP_BASE,
@@ -98,7 +99,7 @@ static void __init _omap_map_io(void)
                iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
        }
 #endif
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
        }
@@ -119,7 +120,7 @@ static void __init _omap_map_io(void)
 
        /* Must init clocks early to assure that timer interrupt works
         */
-       clk_init();
+       omap1_clk_init();
 }
 
 /*
@@ -127,7 +128,9 @@ static void __init _omap_map_io(void)
  */
 void __init omap_map_common_io(void)
 {
-       if (!initialized)
+       if (!initialized) {
                _omap_map_io();
+               omap1_mux_init();
+       }
 }
 
index 192ce6055faabb13f31c6e49c6c4b3b05b3dda9e..ed65a7d2e941cf9228658b323564925ceca3aa2c 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
 
 #include <asm/io.h>
 
@@ -147,11 +148,15 @@ static struct omap_irq_bank omap730_irq_banks[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_irq_bank omap1510_irq_banks[] = {
        { .base_reg = OMAP_IH1_BASE,            .trigger_map = 0xb3febfff },
        { .base_reg = OMAP_IH2_BASE,            .trigger_map = 0xffbfffed },
 };
+static struct omap_irq_bank omap310_irq_banks[] = {
+       { .base_reg = OMAP_IH1_BASE,            .trigger_map = 0xb3faefc3 },
+       { .base_reg = OMAP_IH2_BASE,            .trigger_map = 0x65b3c061 },
+};
 #endif
 
 #if defined(CONFIG_ARCH_OMAP16XX)
@@ -181,11 +186,15 @@ void __init omap_init_irq(void)
                irq_bank_count = ARRAY_SIZE(omap730_irq_banks);
        }
 #endif
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                irq_banks = omap1510_irq_banks;
                irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
        }
+       if (cpu_is_omap310()) {
+               irq_banks = omap310_irq_banks;
+               irq_bank_count = ARRAY_SIZE(omap310_irq_banks);
+       }
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
        if (cpu_is_omap16xx()) {
@@ -226,9 +235,11 @@ void __init omap_init_irq(void)
        }
 
        /* Unmask level 2 handler */
-       if (cpu_is_omap730()) {
+
+       if (cpu_is_omap730())
                omap_unmask_irq(INT_730_IH2_IRQ);
-       } else {
-               omap_unmask_irq(INT_IH2_IRQ);
-       }
+       else if (cpu_is_omap1510())
+               omap_unmask_irq(INT_1510_IH2_IRQ);
+       else if (cpu_is_omap16xx())
+               omap_unmask_irq(INT_1610_IH2_IRQ);
 }
index 399010c140369e31d40c85cca9166d260de8dd76..6506508159157129e85ccc8400119849f448fc6e 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/hardware.h>
 #include <asm/leds.h>
 #include <asm/system.h>
+#include <asm/mach-types.h>
 
 #include <asm/arch/fpga.h>
 #include <asm/arch/gpio.h>
@@ -63,14 +64,19 @@ void h2p2_dbg_leds_event(led_event_t evt)
        case led_stop:
        case led_halted:
                /* all leds off during suspend or shutdown */
-               omap_set_gpio_dataout(GPIO_TIMER, 0);
-               omap_set_gpio_dataout(GPIO_IDLE, 0);
+
+               if (! machine_is_omap_perseus2()) {
+                       omap_set_gpio_dataout(GPIO_TIMER, 0);
+                       omap_set_gpio_dataout(GPIO_IDLE, 0);
+               }
+
                __raw_writew(~0, &fpga->leds);
                led_state &= ~LED_STATE_ENABLED;
                if (evt == led_halted) {
                        iounmap(fpga);
                        fpga = NULL;
                }
+
                goto done;
 
        case led_claim:
@@ -85,18 +91,37 @@ void h2p2_dbg_leds_event(led_event_t evt)
 #ifdef CONFIG_LEDS_TIMER
        case led_timer:
                led_state ^= LED_TIMER_ON;
-               omap_set_gpio_dataout(GPIO_TIMER, led_state & LED_TIMER_ON);
-               goto done;
+
+               if (machine_is_omap_perseus2())
+                       hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER;
+               else {
+                       omap_set_gpio_dataout(GPIO_TIMER, led_state & LED_TIMER_ON);
+                       goto done;
+               }
+
+               break;
 #endif
 
 #ifdef CONFIG_LEDS_CPU
        case led_idle_start:
-               omap_set_gpio_dataout(GPIO_IDLE, 1);
-               goto done;
+               if (machine_is_omap_perseus2())
+                       hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE;
+               else {
+                       omap_set_gpio_dataout(GPIO_IDLE, 1);
+                       goto done;
+               }
+
+               break;
 
        case led_idle_end:
-               omap_set_gpio_dataout(GPIO_IDLE, 0);
-               goto done;
+               if (machine_is_omap_perseus2())
+                       hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE;
+               else {
+                       omap_set_gpio_dataout(GPIO_IDLE, 0);
+                       goto done;
+               }
+
+               break;
 #endif
 
        case led_green_on:
@@ -135,7 +160,7 @@ void h2p2_dbg_leds_event(led_event_t evt)
        /*
         *  Actually burn the LEDs
         */
-       if (led_state & LED_STATE_CLAIMED)
+       if (led_state & LED_STATE_ENABLED)
                __raw_writew(~hw_led_state, &fpga->leds);
 
 done:
index 5c6b1bb6e722deda5bf715e5435498b2846c7228..3f9dcac4fd41abbee1b17346ffee28d06346f8ad 100644 (file)
@@ -33,7 +33,6 @@ omap_leds_init(void)
 
        if (machine_is_omap_h2()
                        || machine_is_omap_h3()
-                       || machine_is_omap_perseus2()
 #ifdef CONFIG_OMAP_OSK_MISTRAL
                        || machine_is_omap_osk()
 #endif
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
new file mode 100644 (file)
index 0000000..d4b8d62
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * linux/arch/arm/mach-omap1/mux.c
+ *
+ * OMAP1 pin multiplexing configurations
+ *
+ * Copyright (C) 2003 - 2005 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>
+
+#include <asm/arch/mux.h>
+
+#ifdef CONFIG_OMAP_MUX
+
+#ifdef CONFIG_ARCH_OMAP730
+struct pin_config __initdata_or_module omap730_pins[] = {
+MUX_CFG_730("E2_730_KBR0",     12,   21,    0,   0,   20,   1,   NA,    0,  0)
+MUX_CFG_730("J7_730_KBR1",     12,   25,    0,   0,   24,   1,   NA,    0,  0)
+MUX_CFG_730("E1_730_KBR2",     12,   29,    0,   0,   28,   1,   NA,    0,  0)
+MUX_CFG_730("F3_730_KBR3",     13,    1,    0,   0,   0,    1,   NA,    0,  0)
+MUX_CFG_730("D2_730_KBR4",     13,    5,    0,   0,   4,    1,   NA,    0,  0)
+MUX_CFG_730("C2_730_KBC0",     13,    9,    0,   0,    8,   1,   NA,    0,  0)
+MUX_CFG_730("D3_730_KBC1",     13,   13,    0,   0,   12,   1,   NA,    0,  0)
+MUX_CFG_730("E4_730_KBC2",     13,   17,    0,   0,   16,   1,   NA,    0,  0)
+MUX_CFG_730("F4_730_KBC3",     13,   21,    0,   0,   20,   1,   NA,    0,  0)
+MUX_CFG_730("E3_730_KBC4",     13,   25,    0,   0,   24,   1,   NA,    0,  0)
+};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+struct pin_config __initdata_or_module omap1xxx_pins[] = {
+/*
+ *      description            mux  mode   mux  pull pull  pull  pu_pd  pu  dbg
+ *                             reg  offset mode reg  bit   ena   reg
+ */
+MUX_CFG("UART1_TX",             9,   21,    1,   2,   3,   0,   NA,     0,  0)
+MUX_CFG("UART1_RTS",            9,   12,    1,   2,   0,   0,   NA,     0,  0)
+
+/* UART2 (COM_UART_GATING), conflicts with USB2 */
+MUX_CFG("UART2_TX",             C,   27,    1,   3,   3,   0,   NA,     0,  0)
+MUX_CFG("UART2_RX",             C,   18,    0,   3,   1,   1,   NA,     0,  0)
+MUX_CFG("UART2_CTS",            C,   21,    0,   3,   1,   1,   NA,     0,  0)
+MUX_CFG("UART2_RTS",            C,   24,    1,   3,   2,   0,   NA,     0,  0)
+
+/* UART3 (GIGA_UART_GATING) */
+MUX_CFG("UART3_TX",             6,    0,    1,   0,  30,   0,   NA,     0,  0)
+MUX_CFG("UART3_RX",             6,    3,    0,   0,  31,   1,   NA,     0,  0)
+MUX_CFG("UART3_CTS",            5,   12,    2,   0,  24,   0,   NA,     0,  0)
+MUX_CFG("UART3_RTS",            5,   15,    2,   0,  25,   0,   NA,     0,  0)
+MUX_CFG("UART3_CLKREQ",                 9,   27,    0,   2,   5,   0,   NA,     0,  0)
+MUX_CFG("UART3_BCLK",           A,    0,    0,   2,   6,   0,   NA,     0,  0)
+MUX_CFG("Y15_1610_UART3_RTS",   A,    0,    1,   2,   6,   0,   NA,     0,  0)
+
+/* PWT & PWL, conflicts with UART3 */
+MUX_CFG("PWT",                  6,    0,    2,   0,  30,   0,   NA,     0,  0)
+MUX_CFG("PWL",                  6,    3,    1,   0,  31,   1,   NA,     0,  0)
+
+/* USB internal master generic */
+MUX_CFG("R18_USB_VBUS",                 7,    9,    2,   1,  11,   0,   NA,     0,  1)
+MUX_CFG("R18_1510_USB_GPIO0",   7,    9,    0,   1,  11,   1,   NA,     0,  1)
+/* works around erratum:  W4_USB_PUEN and W4_USB_PUDIS are switched! */
+MUX_CFG("W4_USB_PUEN",          D,    3,    3,   3,   5,   1,   NA,     0,  1)
+MUX_CFG("W4_USB_CLKO",          D,    3,    1,   3,   5,   0,   NA,     0,  1)
+MUX_CFG("W4_USB_HIGHZ",                 D,    3,    4,   3,   5,   0,    3,     0,  1)
+MUX_CFG("W4_GPIO58",            D,    3,    7,   3,   5,   0,    3,     0,  1)
+
+/* USB1 master */
+MUX_CFG("USB1_SUSP",            8,   27,    2,   1,  27,   0,   NA,     0,  1)
+MUX_CFG("USB1_SE0",             9,    0,    2,   1,  28,   0,   NA,     0,  1)
+MUX_CFG("W13_1610_USB1_SE0",    9,    0,    4,   1,  28,   0,   NA,     0,  1)
+MUX_CFG("USB1_TXEN",            9,    3,    2,   1,  29,   0,   NA,     0,  1)
+MUX_CFG("USB1_TXD",             9,   24,    1,   2,   4,   0,   NA,     0,  1)
+MUX_CFG("USB1_VP",              A,    3,    1,   2,   7,   0,   NA,     0,  1)
+MUX_CFG("USB1_VM",              A,    6,    1,   2,   8,   0,   NA,     0,  1)
+MUX_CFG("USB1_RCV",             A,    9,    1,   2,   9,   0,   NA,     0,  1)
+MUX_CFG("USB1_SPEED",           A,   12,    2,   2,  10,   0,   NA,     0,  1)
+MUX_CFG("R13_1610_USB1_SPEED",  A,   12,    5,   2,  10,   0,   NA,     0,  1)
+MUX_CFG("R13_1710_USB1_SEO",    A,   12,    5,   2,  10,   0,   NA,     0,  1)
+
+/* USB2 master */
+MUX_CFG("USB2_SUSP",            B,    3,    1,   2,  17,   0,   NA,     0,  1)
+MUX_CFG("USB2_VP",              B,    6,    1,   2,  18,   0,   NA,     0,  1)
+MUX_CFG("USB2_TXEN",            B,    9,    1,   2,  19,   0,   NA,     0,  1)
+MUX_CFG("USB2_VM",              C,   18,    1,   3,   0,   0,   NA,     0,  1)
+MUX_CFG("USB2_RCV",             C,   21,    1,   3,   1,   0,   NA,     0,  1)
+MUX_CFG("USB2_SE0",             C,   24,    2,   3,   2,   0,   NA,     0,  1)
+MUX_CFG("USB2_TXD",             C,   27,    2,   3,   3,   0,   NA,     0,  1)
+
+/* OMAP-1510 GPIO */
+MUX_CFG("R18_1510_GPIO0",       7,    9,    0,   1,  11,   1,    0,     0,  1)
+MUX_CFG("R19_1510_GPIO1",       7,    6,    0,   1,  10,   1,    0,     0,  1)
+MUX_CFG("M14_1510_GPIO2",       7,    3,    0,   1,   9,   1,    0,     0,  1)
+
+/* OMAP1610 GPIO */
+MUX_CFG("P18_1610_GPIO3",       7,    0,    0,   1,   8,   0,   NA,     0,  1)
+MUX_CFG("Y15_1610_GPIO17",      A,    0,    7,   2,   6,   0,   NA,     0,  1)
+
+/* OMAP-1710 GPIO */
+MUX_CFG("R18_1710_GPIO0",        7,    9,    0,   1,  11,   1,    1,     1,  1)
+MUX_CFG("V2_1710_GPIO10",        F,   27,    1,   4,   3,   1,    4,     1,  1)
+MUX_CFG("N21_1710_GPIO14",       6,    9,    0,   1,   1,   1,    1,     1,  1)
+MUX_CFG("W15_1710_GPIO40",       9,   27,    7,   2,   5,   1,    2,     1,  1)
+
+/* MPUIO */
+MUX_CFG("MPUIO2",               7,   18,    0,   1,  14,   1,   NA,     0,  1)
+MUX_CFG("N15_1610_MPUIO2",      7,   18,    0,   1,  14,   1,    1,     0,  1)
+MUX_CFG("MPUIO4",               7,   15,    0,   1,  13,   1,   NA,     0,  1)
+MUX_CFG("MPUIO5",               7,   12,    0,   1,  12,   1,   NA,     0,  1)
+
+MUX_CFG("T20_1610_MPUIO5",      7,   12,    0,   1,  12,   0,    3,     0,  1)
+MUX_CFG("W11_1610_MPUIO6",     10,   15,    2,   3,   8,   0,    3,     0,  1)
+MUX_CFG("V10_1610_MPUIO7",      A,   24,    2,   2,  14,   0,    2,     0,  1)
+MUX_CFG("W11_1610_MPUIO9",     10,   15,    1,   3,   8,   0,    3,     0,  1)
+MUX_CFG("V10_1610_MPUIO10",     A,   24,    1,   2,  14,   0,    2,     0,  1)
+MUX_CFG("W10_1610_MPUIO11",     A,   18,    2,   2,  11,   0,    2,     0,  1)
+MUX_CFG("E20_1610_MPUIO13",     3,   21,    1,   0,   7,   0,    0,     0,  1)
+MUX_CFG("U20_1610_MPUIO14",     9,    6,    6,   0,  30,   0,    0,     0,  1)
+MUX_CFG("E19_1610_MPUIO15",     3,   18,    1,   0,   6,   0,    0,     0,  1)
+
+/* MCBSP2 */
+MUX_CFG("MCBSP2_CLKR",          C,    6,    0,   2,  27,   1,   NA,     0,  1)
+MUX_CFG("MCBSP2_CLKX",          C,    9,    0,   2,  29,   1,   NA,     0,  1)
+MUX_CFG("MCBSP2_DR",            C,    0,    0,   2,  26,   1,   NA,     0,  1)
+MUX_CFG("MCBSP2_DX",            C,   15,    0,   2,  31,   1,   NA,     0,  1)
+MUX_CFG("MCBSP2_FSR",           C,   12,    0,   2,  30,   1,   NA,     0,  1)
+MUX_CFG("MCBSP2_FSX",           C,    3,    0,   2,  27,   1,   NA,     0,  1)
+
+/* MCBSP3 NOTE: Mode must 1 for clock */
+MUX_CFG("MCBSP3_CLKX",          9,    3,    1,   1,  29,   0,   NA,     0,  1)
+
+/* Misc ballouts */
+MUX_CFG("BALLOUT_V8_ARMIO3",    B,   18,    0,   2,  25,   1,   NA,     0,  1)
+MUX_CFG("N20_HDQ",            6,   18,    1,   1,   4,   0,    1,     4,  0)
+
+/* OMAP-1610 MMC2 */
+MUX_CFG("W8_1610_MMC2_DAT0",    B,   21,    6,   2,  23,   1,    2,     1,  1)
+MUX_CFG("V8_1610_MMC2_DAT1",    B,   27,    6,   2,  25,   1,    2,     1,  1)
+MUX_CFG("W15_1610_MMC2_DAT2",   9,   12,    6,   2,   5,   1,    2,     1,  1)
+MUX_CFG("R10_1610_MMC2_DAT3",   B,   18,    6,   2,  22,   1,    2,     1,  1)
+MUX_CFG("Y10_1610_MMC2_CLK",    B,    3,    6,   2,  17,   0,    2,     0,  1)
+MUX_CFG("Y8_1610_MMC2_CMD",     B,   24,    6,   2,  24,   1,    2,     1,  1)
+MUX_CFG("V9_1610_MMC2_CMDDIR",  B,   12,    6,   2,  20,   0,    2,     1,  1)
+MUX_CFG("V5_1610_MMC2_DATDIR0",         B,   15,    6,   2,  21,   0,    2,     1,  1)
+MUX_CFG("W19_1610_MMC2_DATDIR1", 8,   15,    6,          1,  23,   0,    1,     1,  1)
+MUX_CFG("R18_1610_MMC2_CLKIN",  7,    9,    6,   1,  11,   0,    1,    11,  1)
+
+/* OMAP-1610 External Trace Interface */
+MUX_CFG("M19_1610_ETM_PSTAT0",  5,   27,    1,   0,  29,   0,    0,     0,  1)
+MUX_CFG("L15_1610_ETM_PSTAT1",  5,   24,    1,   0,  28,   0,    0,     0,  1)
+MUX_CFG("L18_1610_ETM_PSTAT2",  5,   21,    1,   0,  27,   0,    0,     0,  1)
+MUX_CFG("L19_1610_ETM_D0",      5,   18,    1,   0,  26,   0,    0,     0,  1)
+MUX_CFG("J19_1610_ETM_D6",      5,    0,    1,   0,  20,   0,    0,     0,  1)
+MUX_CFG("J18_1610_ETM_D7",      5,   27,    1,   0,  19,   0,    0,     0,  1)
+
+/* OMAP16XX GPIO */
+MUX_CFG("P20_1610_GPIO4",       6,   27,    0,   1,   7,   0,    1,     1,  1)
+MUX_CFG("V9_1610_GPIO7",        B,   12,    1,   2,  20,   0,    2,     1,  1)
+MUX_CFG("W8_1610_GPIO9",        B,   21,    0,   2,  23,   0,    2,     1,  1)
+MUX_CFG("N20_1610_GPIO11",       6,   18,    0,   1,   4,   0,    1,     1,  1)
+MUX_CFG("N19_1610_GPIO13",      6,   12,    0,   1,   2,   0,    1,     1,  1)
+MUX_CFG("P10_1610_GPIO22",      C,    0,    7,   2,  26,   0,    2,     1,  1)
+MUX_CFG("V5_1610_GPIO24",       B,   15,    7,   2,  21,   0,    2,     1,  1)
+MUX_CFG("AA20_1610_GPIO_41",    9,    9,    7,   1,  31,   0,    1,     1,  1)
+MUX_CFG("W19_1610_GPIO48",      8,   15,    7,   1,  23,   1,    1,     0,  1)
+MUX_CFG("M7_1610_GPIO62",      10,    0,    0,   4,  24,   0,    4,     0,  1)
+MUX_CFG("V14_16XX_GPIO37",      9,   18,    7,   2,   2,   0,    2,     2,  0)
+MUX_CFG("R9_16XX_GPIO18",       C,   18,    7,   3,   0,   0,    3,     0,  0)
+MUX_CFG("L14_16XX_GPIO49",      6,    3,    7,   0,  31,   0,    0,    31,  0)
+
+/* OMAP-1610 uWire */
+MUX_CFG("V19_1610_UWIRE_SCLK",  8,    6,    0,   1,  20,   0,    1,     1,  1)
+MUX_CFG("U18_1610_UWIRE_SDI",   8,    0,    0,   1,  18,   0,    1,     1,  1)
+MUX_CFG("W21_1610_UWIRE_SDO",   8,    3,    0,   1,  19,   0,    1,     1,  1)
+MUX_CFG("N14_1610_UWIRE_CS0",   8,    9,    1,   1,  21,   0,    1,     1,  1)
+MUX_CFG("P15_1610_UWIRE_CS3",   8,   12,    1,   1,  22,   0,    1,     1,  1)
+MUX_CFG("N15_1610_UWIRE_CS1",   7,   18,    2,   1,  14,   0,   NA,     0,  1)
+
+/* OMAP-1610 Flash */
+MUX_CFG("L3_1610_FLASH_CS2B_OE",10,    6,    1,         NA,   0,   0,   NA,     0,  1)
+MUX_CFG("M8_1610_FLASH_CS2B_WE",10,    3,    1,         NA,   0,   0,   NA,     0,  1)
+
+/* First MMC interface, same on 1510, 1610 and 1710 */
+MUX_CFG("MMC_CMD",              A,   27,    0,   2,  15,   1,    2,     1,  1)
+MUX_CFG("MMC_DAT1",             A,   24,    0,   2,  14,   1,    2,     1,  1)
+MUX_CFG("MMC_DAT2",             A,   18,    0,   2,  12,   1,    2,     1,  1)
+MUX_CFG("MMC_DAT0",             B,    0,    0,   2,  16,   1,    2,     1,  1)
+MUX_CFG("MMC_CLK",              A,   21,    0,  NA,   0,   0,   NA,     0,  1)
+MUX_CFG("MMC_DAT3",            10,   15,    0,   3,   8,   1,    3,     1,  1)
+MUX_CFG("M15_1710_MMC_CLKI",    6,   21,    2,   0,   0,   0,   NA,     0,  1)
+MUX_CFG("P19_1710_MMC_CMDDIR",  6,   24,    6,   0,   0,   0,   NA,     0,  1)
+MUX_CFG("P20_1710_MMC_DATDIR0",         6,   27,    5,   0,   0,   0,   NA,     0,  1)
+
+/* OMAP-1610 USB0 alternate configuration */
+MUX_CFG("W9_USB0_TXEN",                 B,   9,     5,   2,  19,   0,    2,     0,  1)
+MUX_CFG("AA9_USB0_VP",          B,   6,     5,   2,  18,   0,    2,     0,  1)
+MUX_CFG("Y5_USB0_RCV",          C,  21,     5,   3,   1,   0,    1,     0,  1)
+MUX_CFG("R9_USB0_VM",           C,  18,     5,   3,   0,   0,    3,     0,  1)
+MUX_CFG("V6_USB0_TXD",          C,  27,     5,   3,   3,   0,    3,     0,  1)
+MUX_CFG("W5_USB0_SE0",          C,  24,     5,   3,   2,   0,    3,     0,  1)
+MUX_CFG("V9_USB0_SPEED",        B,  12,     5,   2,  20,   0,    2,     0,  1)
+MUX_CFG("Y10_USB0_SUSP",        B,   3,     5,   2,  17,   0,    2,     0,  1)
+
+/* USB2 interface */
+MUX_CFG("W9_USB2_TXEN",                 B,   9,     1,  NA,   0,   0,   NA,     0,  1)
+MUX_CFG("AA9_USB2_VP",          B,   6,     1,  NA,   0,   0,   NA,     0,  1)
+MUX_CFG("Y5_USB2_RCV",          C,  21,     1,  NA,   0,   0,   NA,     0,  1)
+MUX_CFG("R9_USB2_VM",           C,  18,     1,  NA,   0,   0,   NA,     0,  1)
+MUX_CFG("V6_USB2_TXD",          C,  27,     2,  NA,   0,   0,   NA,     0,  1)
+MUX_CFG("W5_USB2_SE0",          C,  24,     2,  NA,   0,   0,   NA,     0,  1)
+
+/* 16XX UART */
+MUX_CFG("R13_1610_UART1_TX",    A,  12,     6,   2,  10,   0,    2,    10,  1)
+MUX_CFG("V14_16XX_UART1_RX",    9,  18,     0,   2,   2,   0,    2,     2,  1)
+MUX_CFG("R14_1610_UART1_CTS",   9,  15,     0,   2,   1,   0,    2,     1,  1)
+MUX_CFG("AA15_1610_UART1_RTS",  9,  12,     1,   2,   0,   0,    2,     0,  1)
+MUX_CFG("R9_16XX_UART2_RX",     C,  18,     0,   3,   0,   0,    3,     0,  1)
+MUX_CFG("L14_16XX_UART3_RX",    6,   3,     0,   0,  31,   0,    0,    31,  1)
+
+/* I2C interface */
+MUX_CFG("I2C_SCL",              7,  24,     0,  NA,   0,   0,   NA,     0,  0)
+MUX_CFG("I2C_SDA",              7,  27,     0,  NA,   0,   0,   NA,     0,  0)
+
+/* Keypad */
+MUX_CFG("F18_1610_KBC0",        3,  15,     0,   0,   5,   1,    0,     0,  0)
+MUX_CFG("D20_1610_KBC1",        3,  12,     0,   0,   4,   1,    0,     0,  0)
+MUX_CFG("D19_1610_KBC2",        3,   9,     0,   0,   3,   1,    0,     0,  0)
+MUX_CFG("E18_1610_KBC3",        3,   6,     0,   0,   2,   1,    0,     0,  0)
+MUX_CFG("C21_1610_KBC4",        3,   3,     0,   0,   1,   1,    0,     0,  0)
+MUX_CFG("G18_1610_KBR0",        4,   0,     0,   0,   10,  1,    0,     1,  0)
+MUX_CFG("F19_1610_KBR1",        3,   27,    0,   0,   9,   1,    0,     1,  0)
+MUX_CFG("H14_1610_KBR2",        3,   24,    0,   0,   8,   1,    0,     1,  0)
+MUX_CFG("E20_1610_KBR3",        3,   21,    0,   0,   7,   1,    0,     1,  0)
+MUX_CFG("E19_1610_KBR4",        3,   18,    0,   0,   6,   1,    0,     1,  0)
+MUX_CFG("N19_1610_KBR5",        6,  12,     1,   1,   2,   1,    1,     1,  0)
+
+/* Power management */
+MUX_CFG("T20_1610_LOW_PWR",     7,   12,    1,   NA,   0,   0,   NA,    0,  0)
+
+/* MCLK Settings */
+MUX_CFG("V5_1710_MCLK_ON",      B,   15,    0,   NA,   0,   0,   NA,    0,  0)
+MUX_CFG("V5_1710_MCLK_OFF",     B,   15,    6,   NA,   0,   0,   NA,    0,  0)
+MUX_CFG("R10_1610_MCLK_ON",     B,   18,    0,   NA,  22,   0,   NA,    1,  0)
+MUX_CFG("R10_1610_MCLK_OFF",    B,   18,    6,   2,   22,   1,   2,     1,  1)
+
+/* CompactFlash controller, conflicts with MMC1 */
+MUX_CFG("P11_1610_CF_CD2",      A,   27,    3,   2,   15,   1,   2,     1,  1)
+MUX_CFG("R11_1610_CF_IOIS16",   B,    0,    3,   2,   16,   1,   2,     1,  1)
+MUX_CFG("V10_1610_CF_IREQ",     A,   24,    3,   2,   14,   0,   2,     0,  1)
+MUX_CFG("W10_1610_CF_RESET",    A,   18,    3,   2,   12,   1,   2,     1,  1)
+MUX_CFG("W11_1610_CF_CD1",     10,   15,    3,   3,    8,   1,   3,     1,  1)
+};
+#endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
+
+int __init omap1_mux_init(void)
+{
+
+#ifdef CONFIG_ARCH_OMAP730
+       omap_mux_register(omap730_pins, ARRAY_SIZE(omap730_pins));
+#endif
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+       omap_mux_register(omap1xxx_pins, ARRAY_SIZE(omap1xxx_pins));
+#endif
+
+       return 0;
+}
+
+#endif
index 40c4f7c40e73369d6b7f052ca66e966012b99d67..6810cfb84462827c1e90718c359909e3ed2e9d5f 100644 (file)
@@ -109,9 +109,10 @@ static struct platform_device serial_device = {
  * By default UART2 does not work on Innovator-1510 if you have
  * USB OHCI enabled. To use UART2, you must disable USB2 first.
  */
-void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
+void __init omap_serial_init(void)
 {
        int i;
+       const struct omap_uart_config *info;
 
        if (cpu_is_omap730()) {
                serial_platform_data[0].regshift = 0;
@@ -126,10 +127,14 @@ void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
                serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
        }
 
+       info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
+       if (info == NULL)
+               return;
+
        for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
                unsigned char reg;
 
-               if (ports[i] == 0) {
+               if (!((1 << i) & info->enabled_uarts)) {
                        serial_platform_data[i].membase = NULL;
                        serial_platform_data[i].mapbase = 0;
                        continue;
index 191a9b1ee9b7168f1ef3b561b08f732e55b4c2bf..cdbf4d7620c6ce49df6f813d8f398c96fd084862 100644 (file)
@@ -226,8 +226,8 @@ unsigned long long sched_clock(void)
 
 #ifdef CONFIG_OMAP_32K_TIMER
 
-#ifdef CONFIG_ARCH_OMAP1510
-#error OMAP 32KHz timer does not currently work on 1510!
+#ifdef CONFIG_ARCH_OMAP15XX
+#error OMAP 32KHz timer does not currently work on 15XX!
 #endif
 
 /*
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
new file mode 100644 (file)
index 0000000..5788809
--- /dev/null
@@ -0,0 +1,22 @@
+comment "OMAP Core Type"
+       depends on ARCH_OMAP2
+
+config ARCH_OMAP24XX
+       bool "OMAP24xx Based System"
+       depends on ARCH_OMAP2
+
+config ARCH_OMAP2420
+       bool "OMAP2420 support"
+       depends on ARCH_OMAP24XX
+
+comment "OMAP Board Type"
+       depends on ARCH_OMAP2
+
+config MACH_OMAP_GENERIC
+       bool "Generic OMAP board"
+       depends on ARCH_OMAP2 && ARCH_OMAP24XX
+
+config MACH_OMAP_H4
+       bool "OMAP 2420 H4 board"
+       depends on ARCH_OMAP2 && ARCH_OMAP24XX
+
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
new file mode 100644 (file)
index 0000000..4204116
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o
+
+obj-$(CONFIG_OMAP_MPU_TIMER)           += timer-gp.o
+
+# Specific board support
+obj-$(CONFIG_MACH_OMAP_GENERIC)                += board-generic.o
+obj-$(CONFIG_MACH_OMAP_H4)             += board-h4.o
+
diff --git a/arch/arm/mach-omap2/Makefile.boot b/arch/arm/mach-omap2/Makefile.boot
new file mode 100644 (file)
index 0000000..565aff7
--- /dev/null
@@ -0,0 +1,3 @@
+  zreladdr-y           := 0x80008000
+params_phys-y          := 0x80000100
+initrd_phys-y          := 0x80800000
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
new file mode 100644 (file)
index 0000000..c602e7a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/board-generic.c
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ *
+ * Modified from mach-omap/omap1/board-generic.c
+ *
+ * Code for generic OMAP2 board. Should work on many OMAP2 systems where
+ * the bootloader passes the board-specific data to the kernel.
+ * Do not put any board specific code to this file; create a new machine
+ * type if you need custom low-level initializations.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+
+static void __init omap_generic_init_irq(void)
+{
+       omap_init_irq();
+}
+
+static struct omap_uart_config generic_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_mmc_config generic_mmc_config __initdata = {
+       .mmc [0] = {
+               .enabled        = 0,
+               .wire4          = 0,
+               .wp_pin         = -1,
+               .power_pin      = -1,
+               .switch_pin     = -1,
+       },
+};
+
+static struct omap_board_config_kernel generic_config[] = {
+       { OMAP_TAG_UART,        &generic_uart_config },
+       { OMAP_TAG_MMC,         &generic_mmc_config },
+};
+
+static void __init omap_generic_init(void)
+{
+       omap_board_config = generic_config;
+       omap_board_config_size = ARRAY_SIZE(generic_config);
+       omap_serial_init();
+}
+
+static void __init omap_generic_map_io(void)
+{
+       omap_map_common_io();
+}
+
+MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
+       /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
+       .phys_ram       = 0x80000000,
+       .phys_io        = 0x48000000,
+       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = omap_generic_map_io,
+       .init_irq       = omap_generic_init_irq,
+       .init_machine   = omap_generic_init,
+       .timer          = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
new file mode 100644 (file)
index 0000000..f255446
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/board-h4.c
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ *
+ * Modified from mach-omap/omap1/board-generic.c
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include <asm/arch/prcm.h>
+
+#include <asm/io.h>
+#include <asm/delay.h>
+
+static struct mtd_partition h4_partitions[] = {
+       /* bootloader (U-Boot, etc) in first sector */
+       {
+             .name             = "bootloader",
+             .offset           = 0,
+             .size             = SZ_128K,
+             .mask_flags       = MTD_WRITEABLE, /* force read-only */
+       },
+       /* bootloader params in the next sector */
+       {
+             .name             = "params",
+             .offset           = MTDPART_OFS_APPEND,
+             .size             = SZ_128K,
+             .mask_flags       = 0,
+       },
+       /* kernel */
+       {
+             .name             = "kernel",
+             .offset           = MTDPART_OFS_APPEND,
+             .size             = SZ_2M,
+             .mask_flags       = 0
+       },
+       /* file system */
+       {
+             .name             = "filesystem",
+             .offset           = MTDPART_OFS_APPEND,
+             .size             = MTDPART_SIZ_FULL,
+             .mask_flags       = 0
+       }
+};
+
+static struct flash_platform_data h4_flash_data = {
+       .map_name       = "cfi_probe",
+       .width          = 2,
+       .parts          = h4_partitions,
+       .nr_parts       = ARRAY_SIZE(h4_partitions),
+};
+
+static struct resource h4_flash_resource = {
+       .start          = H4_CS0_BASE,
+       .end            = H4_CS0_BASE + SZ_64M - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device h4_flash_device = {
+       .name           = "omapflash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &h4_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &h4_flash_resource,
+};
+
+static struct resource h4_smc91x_resources[] = {
+       [0] = {
+               .start  = OMAP24XX_ETHR_START,          /* Physical */
+               .end    = OMAP24XX_ETHR_START + 0xf,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
+               .end    = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device h4_smc91x_device = {
+       .name           = "smc91x",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(h4_smc91x_resources),
+       .resource       = h4_smc91x_resources,
+};
+
+static struct platform_device *h4_devices[] __initdata = {
+       &h4_smc91x_device,
+       &h4_flash_device,
+};
+
+static inline void __init h4_init_smc91x(void)
+{
+       /* Make sure CS1 timings are correct */
+       GPMC_CONFIG1_1 = 0x00011200;
+       GPMC_CONFIG2_1 = 0x001f1f01;
+       GPMC_CONFIG3_1 = 0x00080803;
+       GPMC_CONFIG4_1 = 0x1c091c09;
+       GPMC_CONFIG5_1 = 0x041f1f1f;
+       GPMC_CONFIG6_1 = 0x000004c4;
+       GPMC_CONFIG7_1 = 0x00000f40 | (0x08000000 >> 24);
+       udelay(100);
+
+       omap_cfg_reg(M15_24XX_GPIO92);
+       if (omap_request_gpio(OMAP24XX_ETHR_GPIO_IRQ) < 0) {
+               printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+                       OMAP24XX_ETHR_GPIO_IRQ);
+               return;
+       }
+       omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1);
+}
+
+static void __init omap_h4_init_irq(void)
+{
+       omap_init_irq();
+       omap_gpio_init();
+       h4_init_smc91x();
+}
+
+static struct omap_uart_config h4_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_mmc_config h4_mmc_config __initdata = {
+       .mmc [0] = {
+               .enabled        = 1,
+               .wire4          = 1,
+               .wp_pin         = -1,
+               .power_pin      = -1,
+               .switch_pin     = -1,
+       },
+};
+
+static struct omap_lcd_config h4_lcd_config __initdata = {
+       .panel_name     = "h4",
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel h4_config[] = {
+       { OMAP_TAG_UART,        &h4_uart_config },
+       { OMAP_TAG_MMC,         &h4_mmc_config },
+       { OMAP_TAG_LCD,         &h4_lcd_config },
+};
+
+static void __init omap_h4_init(void)
+{
+       /*
+        * Make sure the serial ports are muxed on at this point.
+        * You have to mux them off in device drivers later on
+        * if not needed.
+        */
+       platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
+       omap_board_config = h4_config;
+       omap_board_config_size = ARRAY_SIZE(h4_config);
+       omap_serial_init();
+}
+
+static void __init omap_h4_map_io(void)
+{
+       omap_map_common_io();
+}
+
+MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
+       /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
+       .phys_ram       = 0x80000000,
+       .phys_io        = 0x48000000,
+       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = omap_h4_map_io,
+       .init_irq       = omap_h4_init_irq,
+       .init_machine   = omap_h4_init,
+       .timer          = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
new file mode 100644 (file)
index 0000000..74c0524
--- /dev/null
@@ -0,0 +1,1129 @@
+/*
+ *  linux/arch/arm/mach-omap2/clock.c
+ *
+ *  Copyright (C) 2005 Texas Instruments Inc.
+ *  Richard Woodruff <r-woodruff2@ti.com>
+ *  Created for OMAP2.
+ *
+ *  Cleaned up and modified to use omap shared clock framework by
+ *  Tony Lindgren <tony@atomide.com>
+ *
+ *  Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
+ *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.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/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+
+#include <asm/hardware/clock.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/prcm.h>
+
+#include "clock.h"
+
+//#define DOWN_VARIABLE_DPLL 1                 /* Experimental */
+
+static struct prcm_config *curr_prcm_set;
+static struct memory_timings mem_timings;
+static u32 curr_perf_level = PRCM_FULL_SPEED;
+
+/*-------------------------------------------------------------------------
+ * Omap2 specific clock functions
+ *-------------------------------------------------------------------------*/
+
+/* Recalculate SYST_CLK */
+static void omap2_sys_clk_recalc(struct clk * clk)
+{
+       u32 div = PRCM_CLKSRC_CTRL;
+       div &= (1 << 7) | (1 << 6);     /* Test if ext clk divided by 1 or 2 */
+       div >>= clk->rate_offset;
+       clk->rate = (clk->parent->rate / div);
+       propagate_rate(clk);
+}
+
+static u32 omap2_get_dpll_rate(struct clk * tclk)
+{
+       int dpll_clk, dpll_mult, dpll_div, amult;
+
+       dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff;    /* 10 bits */
+       dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f;        /* 4 bits */
+       dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1);
+       amult = CM_CLKSEL2_PLL & 0x3;
+       dpll_clk *= amult;
+
+       return dpll_clk;
+}
+
+static void omap2_followparent_recalc(struct clk *clk)
+{
+       followparent_recalc(clk);
+}
+
+static void omap2_propagate_rate(struct clk * clk)
+{
+       if (!(clk->flags & RATE_FIXED))
+               clk->rate = clk->parent->rate;
+
+       propagate_rate(clk);
+}
+
+/* Enable an APLL if off */
+static void omap2_clk_fixed_enable(struct clk *clk)
+{
+       u32 cval, i=0;
+
+       if (clk->enable_bit == 0xff)                    /* Parent will do it */
+               return;
+
+       cval = CM_CLKEN_PLL;
+
+       if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit))
+               return;
+
+       cval &= ~(0x3 << clk->enable_bit);
+       cval |= (0x3 << clk->enable_bit);
+       CM_CLKEN_PLL = cval;
+
+       if (clk == &apll96_ck)
+               cval = (1 << 8);
+       else if (clk == &apll54_ck)
+               cval = (1 << 6);
+
+       while (!CM_IDLEST_CKGEN & cval) {               /* Wait for lock */
+               ++i;
+               udelay(1);
+               if (i == 100000)
+                       break;
+       }
+}
+
+/* Enables clock without considering parent dependencies or use count
+ * REVISIT: Maybe change this to use clk->enable like on omap1?
+ */
+static int omap2_clk_enable(struct clk * clk)
+{
+       u32 regval32;
+
+       if (clk->flags & ALWAYS_ENABLED)
+               return 0;
+
+       if (unlikely(clk->enable_reg == 0)) {
+               printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+                      clk->name);
+               return 0;
+       }
+
+       if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
+               omap2_clk_fixed_enable(clk);
+               return 0;
+       }
+
+       regval32 = __raw_readl(clk->enable_reg);
+       regval32 |= (1 << clk->enable_bit);
+       __raw_writel(regval32, clk->enable_reg);
+
+       return 0;
+}
+
+/* Stop APLL */
+static void omap2_clk_fixed_disable(struct clk *clk)
+{
+       u32 cval;
+
+       if(clk->enable_bit == 0xff)             /* let parent off do it */
+               return;
+
+       cval = CM_CLKEN_PLL;
+       cval &= ~(0x3 << clk->enable_bit);
+       CM_CLKEN_PLL = cval;
+}
+
+/* Disables clock without considering parent dependencies or use count */
+static void omap2_clk_disable(struct clk *clk)
+{
+       u32 regval32;
+
+       if (clk->enable_reg == 0)
+               return;
+
+       if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
+               omap2_clk_fixed_disable(clk);
+               return;
+       }
+
+       regval32 = __raw_readl(clk->enable_reg);
+       regval32 &= ~(1 << clk->enable_bit);
+       __raw_writel(regval32, clk->enable_reg);
+}
+
+static int omap2_clk_use(struct clk *clk)
+{
+       int ret = 0;
+
+       if (clk->usecount++ == 0) {
+               if (likely((u32)clk->parent))
+                       ret = omap2_clk_use(clk->parent);
+
+               if (unlikely(ret != 0)) {
+                       clk->usecount--;
+                       return ret;
+               }
+
+               ret = omap2_clk_enable(clk);
+
+               if (unlikely(ret != 0) && clk->parent) {
+                       omap2_clk_unuse(clk->parent);
+                       clk->usecount--;
+               }
+       }
+
+       return ret;
+}
+
+static void omap2_clk_unuse(struct clk *clk)
+{
+       if (clk->usecount > 0 && !(--clk->usecount)) {
+               omap2_clk_disable(clk);
+               if (likely((u32)clk->parent))
+                       omap2_clk_unuse(clk->parent);
+       }
+}
+
+/*
+ * Uses the current prcm set to tell if a rate is valid.
+ * You can go slower, but not faster within a given rate set.
+ */
+static u32 omap2_dpll_round_rate(unsigned long target_rate)
+{
+       u32 high, low;
+
+       if ((CM_CLKSEL2_PLL & 0x3) == 1) {      /* DPLL clockout */
+               high = curr_prcm_set->dpll_speed * 2;
+               low = curr_prcm_set->dpll_speed;
+       } else {                                /* DPLL clockout x 2 */
+               high = curr_prcm_set->dpll_speed;
+               low = curr_prcm_set->dpll_speed / 2;
+       }
+
+#ifdef DOWN_VARIABLE_DPLL
+       if (target_rate > high)
+               return high;
+       else
+               return target_rate;
+#else
+       if (target_rate > low)
+               return high;
+       else
+               return low;
+#endif
+
+}
+
+/*
+ * Used for clocks that are part of CLKSEL_xyz governed clocks.
+ * REVISIT: Maybe change to use clk->enable() functions like on omap1?
+ */
+static void omap2_clksel_recalc(struct clk * clk)
+{
+       u32 fixed = 0, div = 0;
+
+       if (clk == &dpll_ck) {
+               clk->rate = omap2_get_dpll_rate(clk);
+               fixed = 1;
+               div = 0;
+       }
+
+       if (clk == &iva1_mpu_int_ifck) {
+               div = 2;
+               fixed = 1;
+       }
+
+       if ((clk == &dss1_fck) && ((CM_CLKSEL1_CORE & (0x1f << 8)) == 0)) {
+               clk->rate = sys_ck.rate;
+               return;
+       }
+
+       if (!fixed) {
+               div = omap2_clksel_get_divisor(clk);
+               if (div == 0)
+                       return;
+       }
+
+       if (div != 0) {
+               if (unlikely(clk->rate == clk->parent->rate / div))
+                       return;
+               clk->rate = clk->parent->rate / div;
+       }
+
+       if (unlikely(clk->flags & RATE_PROPAGATES))
+               propagate_rate(clk);
+}
+
+/*
+ * Finds best divider value in an array based on the source and target
+ * rates. The divider array must be sorted with smallest divider first.
+ */
+static inline u32 omap2_divider_from_table(u32 size, u32 *div_array,
+                                          u32 src_rate, u32 tgt_rate)
+{
+       int i, test_rate;
+
+       if (div_array == NULL)
+               return ~1;
+
+       for (i=0; i < size; i++) {
+               test_rate = src_rate / *div_array;
+               if (test_rate <= tgt_rate)
+                       return *div_array;
+               ++div_array;
+       }
+
+       return ~0;      /* No acceptable divider */
+}
+
+/* 
+ * Find divisor for the given clock and target rate.
+ *
+ * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
+ * they are only settable as part of virtual_prcm set.
+ */
+static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate,
+       u32 *new_div)
+{
+       u32 gfx_div[] = {2, 3, 4};
+       u32 sysclkout_div[] = {1, 2, 4, 8, 16};
+       u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
+       u32 vylnq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
+       u32 best_div = ~0, asize = 0;
+       u32 *div_array = NULL;
+       
+       switch (tclk->flags & SRC_RATE_SEL_MASK) {
+       case CM_GFX_SEL1:
+               asize = 3;
+               div_array = gfx_div;
+               break;
+       case CM_PLL_SEL1:
+               return omap2_dpll_round_rate(target_rate);
+       case CM_SYSCLKOUT_SEL1:
+               asize = 5;
+               div_array = sysclkout_div;
+               break;
+       case CM_CORE_SEL1:
+               if(tclk == &dss1_fck){
+                       if(tclk->parent == &core_ck){
+                               asize = 10;
+                               div_array = dss1_div;
+                       } else {
+                               *new_div = 0; /* fixed clk */
+                               return(tclk->parent->rate);
+                       }
+               } else if((tclk == &vlynq_fck) && cpu_is_omap2420()){
+                       if(tclk->parent == &core_ck){
+                               asize = 10;
+                               div_array = vylnq_div;
+                       } else {
+                               *new_div = 0; /* fixed clk */
+                               return(tclk->parent->rate);
+                       }
+               }
+               break;
+       }
+
+       best_div = omap2_divider_from_table(asize, div_array,
+        tclk->parent->rate, target_rate);
+       if (best_div == ~0){
+               *new_div = 1;
+               return best_div; /* signal error */
+       }
+
+       *new_div = best_div;
+       return (tclk->parent->rate / best_div);
+}
+
+/* Given a clock and a rate apply a clock specific rounding function */
+static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       u32 new_div = 0;
+       int valid_rate;
+
+       if (clk->flags & RATE_FIXED)
+               return clk->rate;
+
+       if (clk->flags & RATE_CKCTL) {
+               valid_rate = omap2_clksel_round_rate(clk, rate, &new_div);
+               return valid_rate;
+       }
+
+       if (clk->round_rate != 0)
+               return clk->round_rate(clk, rate);
+
+       return clk->rate;
+}
+
+/*
+ * Check the DLL lock state, and return tue if running in unlock mode.
+ * This is needed to compenste for the shifted DLL value in unlock mode.
+ */
+static u32 omap2_dll_force_needed(void)
+{
+       u32 dll_state = SDRC_DLLA_CTRL;         /* dlla and dllb are a set */
+
+       if ((dll_state & (1 << 2)) == (1 << 2))
+               return 1;
+       else
+               return 0;
+}
+
+static void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+{
+       unsigned long dll_cnt;
+       u32 fast_dll = 0;
+
+       mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+       /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+        * In the case of 2422, its ok to use CS1 instead of CS0.
+        */
+
+#if 0  /* FIXME: Enable after 24xx cpu detection works */
+       ctype = get_cpu_type();
+       if (cpu_is_omap2422())
+               mem_timings.base_cs = 1;
+       else
+#endif
+               mem_timings.base_cs = 0;
+
+       if (mem_timings.m_type != M_DDR)
+               return;
+
+       /* With DDR we need to determine the low frequency DLL value */
+       if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
+               mem_timings.dll_mode = M_UNLOCK;
+       else
+               mem_timings.dll_mode = M_LOCK;
+
+       if (mem_timings.base_cs == 0) {
+               fast_dll = SDRC_DLLA_CTRL;
+               dll_cnt = SDRC_DLLA_STATUS & 0xff00;
+       } else {
+               fast_dll = SDRC_DLLB_CTRL;
+               dll_cnt = SDRC_DLLB_STATUS & 0xff00;
+       }
+       if (force_lock_to_unlock_mode) {
+               fast_dll &= ~0xff00;
+               fast_dll |= dll_cnt;            /* Current lock mode */
+       }
+       mem_timings.fast_dll_ctrl = fast_dll;
+
+       /* No disruptions, DDR will be offline & C-ABI not followed */
+       omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
+                           mem_timings.fast_dll_ctrl,
+                           mem_timings.base_cs,
+                           force_lock_to_unlock_mode);
+       mem_timings.slow_dll_ctrl &= 0xff00;    /* Keep lock value */
+
+       /* Turn status into unlock ctrl */
+       mem_timings.slow_dll_ctrl |=
+               ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
+
+       /* 90 degree phase for anything below 133Mhz */
+       mem_timings.slow_dll_ctrl |= (1 << 1);
+}
+
+static u32 omap2_reprogram_sdrc(u32 level, u32 force)
+{
+       u32 prev = curr_perf_level, flags;
+
+       if ((curr_perf_level == level) && !force)
+               return prev;
+
+       if (level == PRCM_HALF_SPEED) {
+               local_irq_save(flags);
+               PRCM_VOLTSETUP = 0xffff;
+               omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
+                                         mem_timings.slow_dll_ctrl,
+                                         mem_timings.m_type);
+               curr_perf_level = PRCM_HALF_SPEED;
+               local_irq_restore(flags);
+       }
+       if (level == PRCM_FULL_SPEED) {
+               local_irq_save(flags);
+               PRCM_VOLTSETUP = 0xffff;
+               omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
+                                         mem_timings.fast_dll_ctrl,
+                                         mem_timings.m_type);
+               curr_perf_level = PRCM_FULL_SPEED;
+               local_irq_restore(flags);
+       }
+
+       return prev;
+}
+
+static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
+{
+       u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
+       u32 bypass = 0;
+       struct prcm_config tmpset;
+       int ret = -EINVAL;
+
+       local_irq_save(flags);
+       cur_rate = omap2_get_dpll_rate(&dpll_ck);
+       mult = CM_CLKSEL2_PLL & 0x3;
+
+       if ((rate == (cur_rate / 2)) && (mult == 2)) {
+               omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
+       } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
+               omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
+       } else if (rate != cur_rate) {
+               valid_rate = omap2_dpll_round_rate(rate);
+               if (valid_rate != rate)
+                       goto dpll_exit;
+
+               if ((CM_CLKSEL2_PLL & 0x3) == 1)
+                       low = curr_prcm_set->dpll_speed;
+               else
+                       low = curr_prcm_set->dpll_speed / 2;
+
+               tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL;
+               tmpset.cm_clksel1_pll &= ~(0x3FFF << 8);
+               div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
+               tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL;
+               tmpset.cm_clksel2_pll &= ~0x3;
+               if (rate > low) {
+                       tmpset.cm_clksel2_pll |= 0x2;
+                       mult = ((rate / 2) / 1000000);
+                       done_rate = PRCM_FULL_SPEED;
+               } else {
+                       tmpset.cm_clksel2_pll |= 0x1;
+                       mult = (rate / 1000000);
+                       done_rate = PRCM_HALF_SPEED;
+               }
+               tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12));
+
+               /* Worst case */
+               tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
+
+               if (rate == curr_prcm_set->xtal_speed)  /* If asking for 1-1 */
+                       bypass = 1;
+
+               omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */
+
+               /* Force dll lock mode */
+               omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
+                              bypass);
+
+               /* Errata: ret dll entry state */
+               omap2_init_memory_params(omap2_dll_force_needed());
+               omap2_reprogram_sdrc(done_rate, 0);
+       }
+       omap2_clksel_recalc(&dpll_ck);
+       ret = 0;
+
+dpll_exit:
+       local_irq_restore(flags);
+       return(ret);
+}
+
+/* Just return the MPU speed */
+static void omap2_mpu_recalc(struct clk * clk)
+{
+       clk->rate = curr_prcm_set->mpu_speed;
+}
+
+/*
+ * Look for a rate equal or less than the target rate given a configuration set.
+ *
+ * What's not entirely clear is "which" field represents the key field.
+ * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
+ * just uses the ARM rates.
+ */
+static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
+{
+       struct prcm_config * ptr;
+       long highest_rate;
+
+       if (clk != &virt_prcm_set)
+               return -EINVAL;
+
+       highest_rate = -EINVAL;
+
+       for (ptr = rate_table; ptr->mpu_speed; ptr++) {
+               if (ptr->xtal_speed != sys_ck.rate)
+                       continue;
+
+               highest_rate = ptr->mpu_speed;
+
+               /* Can check only after xtal frequency check */
+               if (ptr->mpu_speed <= rate)
+                       break;
+       }
+       return highest_rate;
+}
+
+/*
+ * omap2_convert_field_to_div() - turn field value into integer divider
+ */
+static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
+{
+       u32 i;
+       u32 clkout_array[] = {1, 2, 4, 8, 16};
+
+       if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
+               for (i = 0; i < 5; i++) {
+                       if (field_val == i)
+                               return clkout_array[i];
+               }
+               return ~0;
+       } else
+               return field_val;
+}
+
+/*
+ * Returns the CLKSEL divider register value
+ * REVISIT: This should be cleaned up to work nicely with void __iomem *
+ */
+static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
+                           struct clk *clk)
+{
+       int ret = ~0;
+       u32 reg_val, div_off;
+       u32 div_addr = 0;
+       u32 mask = ~0;
+
+       div_off = clk->rate_offset;
+
+       switch ((*div_sel & SRC_RATE_SEL_MASK)) {
+       case CM_MPU_SEL1:
+               div_addr = (u32)&CM_CLKSEL_MPU;
+               mask = 0x1f;
+               break;
+       case CM_DSP_SEL1:
+               div_addr = (u32)&CM_CLKSEL_DSP;
+               if (cpu_is_omap2420()) {
+                       if ((div_off == 0) || (div_off == 8))
+                               mask = 0x1f;
+                       else if (div_off == 5)
+                               mask = 0x3;
+               } else if (cpu_is_omap2430()) {
+                       if (div_off == 0)
+                               mask = 0x1f;
+                       else if (div_off == 5)
+                               mask = 0x3;
+               }
+               break;
+       case CM_GFX_SEL1:
+               div_addr = (u32)&CM_CLKSEL_GFX;
+               if (div_off == 0)
+                       mask = 0x7;
+               break;
+       case CM_MODEM_SEL1:
+               div_addr = (u32)&CM_CLKSEL_MDM;
+               if (div_off == 0)
+                       mask = 0xf;
+               break;
+       case CM_SYSCLKOUT_SEL1:
+               div_addr = (u32)&PRCM_CLKOUT_CTRL;
+               if ((div_off == 3) || (div_off = 11))
+                       mask= 0x3;
+               break;
+       case CM_CORE_SEL1:
+               div_addr = (u32)&CM_CLKSEL1_CORE;
+               switch (div_off) {
+               case 0:                                 /* l3 */
+               case 8:                                 /* dss1 */
+               case 15:                                /* vylnc-2420 */
+               case 20:                                /* ssi */
+                       mask = 0x1f; break;
+               case 5:                                 /* l4 */
+                       mask = 0x3; break;
+               case 13:                                /* dss2 */
+                       mask = 0x1; break;
+               case 25:                                /* usb */
+                       mask = 0xf; break;
+               }
+       }
+
+       *field_mask = mask;
+
+       if (unlikely(mask == ~0))
+               div_addr = 0;
+
+       *div_sel = div_addr;
+
+       if (unlikely(div_addr == 0))
+               return ret;
+
+       /* Isolate field */
+       reg_val = __raw_readl((void __iomem *)div_addr) & (mask << div_off);
+
+       /* Normalize back to divider value */
+       reg_val >>= div_off;
+
+       return reg_val;
+}
+
+/*
+ * Return divider to be applied to parent clock.
+ * Return 0 on error.
+ */
+static u32 omap2_clksel_get_divisor(struct clk *clk)
+{
+       int ret = 0;
+       u32 div, div_sel, div_off, field_mask, field_val;
+
+       /* isolate control register */
+       div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+       
+       div_off = clk->rate_offset;
+       field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
+       if (div_sel == 0)
+               return ret;
+
+       div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+       div = omap2_clksel_to_divisor(div_sel, field_val);
+
+       return div;
+}
+
+/* Set the clock rate for a clock source */
+static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+
+{
+       int ret = -EINVAL;
+       void __iomem * reg;
+       u32 div_sel, div_off, field_mask, field_val, reg_val, validrate;
+       u32 new_div = 0;
+
+       if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
+               if (clk == &dpll_ck)
+                       return omap2_reprogram_dpll(clk, rate);
+
+               /* Isolate control register */
+               div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+               div_off = clk->src_offset;
+
+               validrate = omap2_clksel_round_rate(clk, rate, &new_div);
+               if(validrate != rate)
+                       return(ret);
+
+               field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
+               if (div_sel == 0)
+                       return ret;
+
+               if(clk->flags & CM_SYSCLKOUT_SEL1){
+                       switch(new_div){
+                       case 16: field_val = 4; break;
+                       case 8:  field_val = 3; break;
+                       case 4:  field_val = 2; break;
+                       case 2:  field_val = 1; break;
+                       case 1:  field_val = 0; break;
+                       }
+               }
+               else
+                       field_val = new_div;
+
+               reg = (void __iomem *)div_sel;
+
+               reg_val = __raw_readl(reg);
+               reg_val &= ~(field_mask << div_off);
+               reg_val |= (field_val << div_off);
+
+               __raw_writel(reg_val, reg);
+               clk->rate = clk->parent->rate / field_val;
+
+               if (clk->flags & DELAYED_APP)
+                       __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+               ret = 0;
+       } else if (clk->set_rate != 0)
+               ret = clk->set_rate(clk, rate);
+
+       if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
+               propagate_rate(clk);
+
+       return ret;
+}
+
+/* Converts encoded control register address into a full address */
+static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
+                              struct clk *src_clk, u32 *field_mask)
+{
+       u32 val = ~0, src_reg_addr = 0, mask = 0;
+
+       /* Find target control register.*/
+       switch ((*type_to_addr & SRC_RATE_SEL_MASK)) {
+       case CM_CORE_SEL1:
+               src_reg_addr = (u32)&CM_CLKSEL1_CORE;
+               if (reg_offset == 13) {                 /* DSS2_fclk */
+                       mask = 0x1;
+                       if (src_clk == &sys_ck)
+                               val = 0;
+                       if (src_clk == &func_48m_ck)
+                               val = 1;
+               } else if (reg_offset == 8) {           /* DSS1_fclk */
+                       mask = 0x1f;
+                       if (src_clk == &sys_ck)
+                               val = 0;
+                       else if (src_clk == &core_ck)   /* divided clock */
+                               val = 0x10;             /* rate needs fixing */
+               } else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/
+                       mask = 0x1F;
+                       if(src_clk == &func_96m_ck)
+                               val = 0;
+                       else if (src_clk == &core_ck)
+                               val = 0x10;
+               }
+               break;
+       case CM_CORE_SEL2:
+               src_reg_addr = (u32)&CM_CLKSEL2_CORE;
+               mask = 0x3;
+               if (src_clk == &func_32k_ck)
+                       val = 0x0;
+               if (src_clk == &sys_ck)
+                       val = 0x1;
+               if (src_clk == &alt_ck)
+                       val = 0x2;
+               break;
+       case CM_WKUP_SEL1:
+               src_reg_addr = (u32)&CM_CLKSEL2_CORE;
+               mask = 0x3;
+               if (src_clk == &func_32k_ck)
+                       val = 0x0;
+               if (src_clk == &sys_ck)
+                       val = 0x1;
+               if (src_clk == &alt_ck)
+                       val = 0x2;
+               break;
+       case CM_PLL_SEL1:
+               src_reg_addr = (u32)&CM_CLKSEL1_PLL;
+               mask = 0x1;
+               if (reg_offset == 0x3) {
+                       if (src_clk == &apll96_ck)
+                               val = 0;
+                       if (src_clk == &alt_ck)
+                               val = 1;
+               }
+               else if (reg_offset == 0x5) {
+                       if (src_clk == &apll54_ck)
+                               val = 0;
+                       if (src_clk == &alt_ck)
+                               val = 1;
+               }
+               break;
+       case CM_PLL_SEL2:
+               src_reg_addr = (u32)&CM_CLKSEL2_PLL;
+               mask = 0x3;
+               if (src_clk == &func_32k_ck)
+                       val = 0x0;
+               if (src_clk == &dpll_ck)
+                       val = 0x2;
+               break;
+       case CM_SYSCLKOUT_SEL1:
+               src_reg_addr = (u32)&PRCM_CLKOUT_CTRL;
+               mask = 0x3;
+               if (src_clk == &dpll_ck)
+                       val = 0;
+               if (src_clk == &sys_ck)
+                       val = 1;
+               if (src_clk == &func_54m_ck)
+                       val = 2;
+               if (src_clk == &func_96m_ck)
+                       val = 3;
+               break;
+       }
+
+       if (val == ~0)                  /* Catch errors in offset */
+               *type_to_addr = 0;
+       else
+               *type_to_addr = src_reg_addr;
+       *field_mask = mask;
+
+       return val;
+}
+
+static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
+{
+       void __iomem * reg;
+       u32 src_sel, src_off, field_val, field_mask, reg_val, rate;
+       int ret = -EINVAL;
+
+       if (unlikely(clk->flags & CONFIG_PARTICIPANT))
+               return ret;
+
+       if (clk->flags & SRC_SEL_MASK) {        /* On-chip SEL collection */
+               src_sel = (SRC_RATE_SEL_MASK & clk->flags);
+               src_off = clk->src_offset;
+
+               if (src_sel == 0)
+                       goto set_parent_error;
+
+               field_val = omap2_get_src_field(&src_sel, src_off, new_parent,
+                                               &field_mask);
+
+               reg = (void __iomem *)src_sel;
+
+               if (clk->usecount > 0)
+                       omap2_clk_disable(clk);
+
+               /* Set new source value (previous dividers if any in effect) */
+               reg_val = __raw_readl(reg) & ~(field_mask << src_off);
+               reg_val |= (field_val << src_off);
+               __raw_writel(reg_val, reg);
+
+               if (clk->flags & DELAYED_APP)
+                       __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+
+               if (clk->usecount > 0)
+                       omap2_clk_enable(clk);
+
+               clk->parent = new_parent;
+
+               /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
+               if ((new_parent == &core_ck) && (clk == &dss1_fck))
+                       clk->rate = new_parent->rate / 0x10;
+               else
+                       clk->rate = new_parent->rate;
+
+               if (unlikely(clk->flags & RATE_PROPAGATES))
+                       propagate_rate(clk);
+
+               return 0;
+       } else {
+               clk->parent = new_parent;
+               rate = new_parent->rate;
+               omap2_clk_set_rate(clk, rate);
+               ret = 0;
+       }
+
+ set_parent_error:
+       return ret;
+}
+
+/* Sets basic clocks based on the specified rate */
+static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
+{
+       u32 flags, cur_rate, done_rate, bypass = 0;
+       u8 cpu_mask = 0;
+       struct prcm_config *prcm;
+       unsigned long found_speed = 0;
+
+       if (clk != &virt_prcm_set)
+               return -EINVAL;
+
+       /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */
+       if (cpu_is_omap2420())
+               cpu_mask = RATE_IN_242X;
+       else if (cpu_is_omap2430())
+               cpu_mask = RATE_IN_243X;
+
+       for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+               if (!(prcm->flags & cpu_mask))
+                       continue;
+
+               if (prcm->xtal_speed != sys_ck.rate)
+                       continue;
+
+               if (prcm->mpu_speed <= rate) {
+                       found_speed = prcm->mpu_speed;
+                       break;
+               }
+       }
+
+       if (!found_speed) {
+               printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
+        rate / 1000000);
+               return -EINVAL;
+       }
+
+       curr_prcm_set = prcm;
+       cur_rate = omap2_get_dpll_rate(&dpll_ck);
+
+       if (prcm->dpll_speed == cur_rate / 2) {
+               omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
+       } else if (prcm->dpll_speed == cur_rate * 2) {
+               omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
+       } else if (prcm->dpll_speed != cur_rate) {
+               local_irq_save(flags);
+
+               if (prcm->dpll_speed == prcm->xtal_speed)
+                       bypass = 1;
+
+               if ((prcm->cm_clksel2_pll & 0x3) == 2)
+                       done_rate = PRCM_FULL_SPEED;
+               else
+                       done_rate = PRCM_HALF_SPEED;
+
+               /* MPU divider */
+               CM_CLKSEL_MPU = prcm->cm_clksel_mpu;
+
+               /* dsp + iva1 div(2420), iva2.1(2430) */
+               CM_CLKSEL_DSP = prcm->cm_clksel_dsp;
+
+               CM_CLKSEL_GFX = prcm->cm_clksel_gfx;
+
+               /* Major subsystem dividers */
+               CM_CLKSEL1_CORE = prcm->cm_clksel1_core;
+               if (cpu_is_omap2430())
+                       CM_CLKSEL_MDM = prcm->cm_clksel_mdm;
+
+               /* x2 to enter init_mem */
+               omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
+
+               omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
+                              bypass);
+
+               omap2_init_memory_params(omap2_dll_force_needed());
+               omap2_reprogram_sdrc(done_rate, 0);
+
+               local_irq_restore(flags);
+       }
+       omap2_clksel_recalc(&dpll_ck);
+
+       return 0;
+}
+
+/*-------------------------------------------------------------------------
+ * Omap2 clock reset and init functions
+ *-------------------------------------------------------------------------*/
+
+static struct clk_functions omap2_clk_functions = {
+       .clk_enable             = omap2_clk_enable,
+       .clk_disable            = omap2_clk_disable,
+       .clk_use                = omap2_clk_use,
+       .clk_unuse              = omap2_clk_unuse,
+       .clk_round_rate         = omap2_clk_round_rate,
+       .clk_set_rate           = omap2_clk_set_rate,
+       .clk_set_parent         = omap2_clk_set_parent,
+};
+
+static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
+{
+       u32 div, aplls, sclk = 13000000;
+
+       aplls = CM_CLKSEL1_PLL;
+       aplls &= ((1 << 23) | (1 << 24) | (1 << 25));
+       aplls >>= 23;                   /* Isolate field, 0,2,3 */
+
+       if (aplls == 0)
+               sclk = 19200000;
+       else if (aplls == 2)
+               sclk = 13000000;
+       else if (aplls == 3)
+               sclk = 12000000;
+
+       div = PRCM_CLKSRC_CTRL;
+       div &= ((1 << 7) | (1 << 6));
+       div >>= sys->rate_offset;
+
+       osc->rate = sclk * div;
+       sys->rate = sclk;
+}
+
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+static void __init omap2_disable_unused_clocks(void)
+{
+       struct clk *ck;
+       u32 regval32;
+
+       list_for_each_entry(ck, &clocks, node) {
+               if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
+                       ck->enable_reg == 0)
+                       continue;
+
+               regval32 = __raw_readl(ck->enable_reg);
+               if ((regval32 & (1 << ck->enable_bit)) == 0)
+                       continue;
+
+               printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
+               omap2_clk_disable(ck);
+       }
+}
+late_initcall(omap2_disable_unused_clocks);
+#endif
+
+/*
+ * Switch the MPU rate if specified on cmdline.
+ * We cannot do this early until cmdline is parsed.
+ */
+static int __init omap2_clk_arch_init(void)
+{
+       if (!mpurate)
+               return -EINVAL;
+       
+       if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+               printk(KERN_ERR "Could not find matching MPU rate\n");
+
+       propagate_rate(&osc_ck);                /* update main root fast */
+       propagate_rate(&func_32k_ck);           /* update main root slow */
+
+       printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
+              "%ld.%01ld/%ld/%ld MHz\n",
+              (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
+              (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
+
+       return 0;
+}
+arch_initcall(omap2_clk_arch_init);
+
+int __init omap2_clk_init(void)
+{
+       struct prcm_config *prcm;
+       struct clk ** clkp;
+       u32 clkrate;
+
+       clk_init(&omap2_clk_functions);
+       omap2_get_crystal_rate(&osc_ck, &sys_ck);
+
+       for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+            clkp++) {
+
+               if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
+                       clk_register(*clkp);
+                       continue;
+               }
+
+               if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
+                       clk_register(*clkp);
+                       continue;
+               }
+       }
+
+       /* Check the MPU rate set by bootloader */
+       clkrate = omap2_get_dpll_rate(&dpll_ck);
+       for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+               if (prcm->xtal_speed != sys_ck.rate)
+                       continue;
+               if (prcm->dpll_speed <= clkrate)
+                        break;
+       }
+       curr_prcm_set = prcm;
+
+       propagate_rate(&osc_ck);                /* update main root fast */
+       propagate_rate(&func_32k_ck);           /* update main root slow */
+
+       printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
+              "%ld.%01ld/%ld/%ld MHz\n",
+              (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
+              (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
+
+       /*
+        * Only enable those clocks we will need, let the drivers
+        * enable other clocks as necessary
+        */
+       clk_use(&sync_32k_ick);
+       clk_use(&omapctrl_ick);
+       if (cpu_is_omap2430())
+               clk_use(&sdrc_ick);
+
+       return 0;
+}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
new file mode 100644 (file)
index 0000000..48d2888
--- /dev/null
@@ -0,0 +1,2103 @@
+/*
+ *  linux/arch/arm/mach-omap24xx/clock.h
+ *
+ *  Copyright (C) 2005 Texas Instruments Inc.
+ *  Richard Woodruff <r-woodruff2@ti.com>
+ *  Created for OMAP2.
+ *
+ *  Copyright (C) 2004 Nokia corporation
+ *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *  Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H
+#define __ARCH_ARM_MACH_OMAP2_CLOCK_H
+
+static void omap2_sys_clk_recalc(struct clk * clk);
+static void omap2_clksel_recalc(struct clk * clk);
+static void omap2_followparent_recalc(struct clk * clk);
+static void omap2_propagate_rate(struct clk * clk);
+static void omap2_mpu_recalc(struct clk * clk);
+static int omap2_select_table_rate(struct clk * clk, unsigned long rate);
+static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate);
+static void omap2_clk_unuse(struct clk *clk);
+static void omap2_sys_clk_recalc(struct clk * clk);
+static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
+static u32 omap2_clksel_get_divisor(struct clk *clk);
+
+
+#define RATE_IN_242X   (1 << 0)
+#define RATE_IN_243X   (1 << 1)
+
+/* Memory timings */
+#define M_DDR          1
+#define M_LOCK_CTRL    (1 << 2)
+#define M_UNLOCK       0
+#define M_LOCK         1
+
+struct memory_timings {
+       u32 m_type;             /* ddr = 1, sdr = 0 */
+       u32 dll_mode;           /* use lock mode = 1, unlock mode = 0 */
+       u32 slow_dll_ctrl;      /* unlock mode, dll value for slow speed */
+       u32 fast_dll_ctrl;      /* unlock mode, dll value for fast speed */
+       u32 base_cs;            /* base chip select to use for calculations */
+};
+
+/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+ * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
+ * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
+ */
+struct prcm_config {
+       unsigned long xtal_speed;       /* crystal rate */
+       unsigned long dpll_speed;       /* dpll: out*xtal*M/(N-1)table_recalc */
+       unsigned long mpu_speed;        /* speed of MPU */
+       unsigned long cm_clksel_mpu;    /* mpu divider */
+       unsigned long cm_clksel_dsp;    /* dsp+iva1 div(2420), iva2.1(2430) */
+       unsigned long cm_clksel_gfx;    /* gfx dividers */
+       unsigned long cm_clksel1_core;  /* major subsystem dividers */
+       unsigned long cm_clksel1_pll;   /* m,n */
+       unsigned long cm_clksel2_pll;   /* dpllx1 or x2 out */
+       unsigned long cm_clksel_mdm;    /* modem dividers 2430 only */
+       unsigned long base_sdrc_rfr;    /* base refresh timing for a set */
+       unsigned char flags;
+};
+
+/* Mask for clksel which support parent settign in set_rate */
+#define SRC_SEL_MASK (CM_CORE_SEL1 | CM_CORE_SEL2 | CM_WKUP_SEL1 | \
+                       CM_PLL_SEL1 | CM_PLL_SEL2 | CM_SYSCLKOUT_SEL1)
+
+/* Mask for clksel regs which support rate operations */
+#define SRC_RATE_SEL_MASK (CM_MPU_SEL1 | CM_DSP_SEL1 | CM_GFX_SEL1 | \
+                       CM_MODEM_SEL1 | CM_CORE_SEL1 | CM_CORE_SEL2 | \
+                       CM_WKUP_SEL1 | CM_PLL_SEL1 | CM_PLL_SEL2 | \
+                       CM_SYSCLKOUT_SEL1)
+
+/*
+ * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
+ * These configurations are characterized by voltage and speed for clocks.
+ * The device is only validated for certain combinations. One way to express
+ * these combinations is via the 'ratio's' which the clocks operate with
+ * respect to each other. These ratio sets are for a given voltage/DPLL
+ * setting. All configurations can be described by a DPLL setting and a ratio
+ * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
+ *
+ * 2430 differs from 2420 in that there are no more phase synchronizers used.
+ * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
+ * 2430 (iva2.1, NOdsp, mdm)
+ */
+
+/* Core fields for cm_clksel, not ratio governed */
+#define RX_CLKSEL_DSS1                 (0x10 << 8)
+#define RX_CLKSEL_DSS2                 (0x0 << 13)
+#define RX_CLKSEL_SSI                  (0x5 << 20)
+
+/*-------------------------------------------------------------------------
+ * Voltage/DPLL ratios
+ *-------------------------------------------------------------------------*/
+
+/* 2430 Ratio's, 2430-Ratio Config 1 */
+#define R1_CLKSEL_L3                   (4 << 0)
+#define R1_CLKSEL_L4                   (2 << 5)
+#define R1_CLKSEL_USB                  (4 << 25)
+#define R1_CM_CLKSEL1_CORE_VAL         R1_CLKSEL_USB | RX_CLKSEL_SSI | \
+                                       RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+                                       R1_CLKSEL_L4 | R1_CLKSEL_L3
+#define R1_CLKSEL_MPU                  (2 << 0)
+#define R1_CM_CLKSEL_MPU_VAL           R1_CLKSEL_MPU
+#define R1_CLKSEL_DSP                  (2 << 0)
+#define R1_CLKSEL_DSP_IF               (2 << 5)
+#define R1_CM_CLKSEL_DSP_VAL           R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF
+#define R1_CLKSEL_GFX                  (2 << 0)
+#define R1_CM_CLKSEL_GFX_VAL           R1_CLKSEL_GFX
+#define R1_CLKSEL_MDM                  (4 << 0)
+#define R1_CM_CLKSEL_MDM_VAL           R1_CLKSEL_MDM
+
+/* 2430-Ratio Config 2 */
+#define R2_CLKSEL_L3                   (6 << 0)
+#define R2_CLKSEL_L4                   (2 << 5)
+#define R2_CLKSEL_USB                  (2 << 25)
+#define R2_CM_CLKSEL1_CORE_VAL         R2_CLKSEL_USB | RX_CLKSEL_SSI | \
+                                       RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+                                       R2_CLKSEL_L4 | R2_CLKSEL_L3
+#define R2_CLKSEL_MPU                  (2 << 0)
+#define R2_CM_CLKSEL_MPU_VAL           R2_CLKSEL_MPU
+#define R2_CLKSEL_DSP                  (2 << 0)
+#define R2_CLKSEL_DSP_IF               (3 << 5)
+#define R2_CM_CLKSEL_DSP_VAL           R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF
+#define R2_CLKSEL_GFX                  (2 << 0)
+#define R2_CM_CLKSEL_GFX_VAL           R2_CLKSEL_GFX
+#define R2_CLKSEL_MDM                  (6 << 0)
+#define R2_CM_CLKSEL_MDM_VAL           R2_CLKSEL_MDM
+
+/* 2430-Ratio Bootm (BYPASS) */
+#define RB_CLKSEL_L3                   (1 << 0)
+#define RB_CLKSEL_L4                   (1 << 5)
+#define RB_CLKSEL_USB                  (1 << 25)
+#define RB_CM_CLKSEL1_CORE_VAL         RB_CLKSEL_USB | RX_CLKSEL_SSI | \
+                                       RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+                                       RB_CLKSEL_L4 | RB_CLKSEL_L3
+#define RB_CLKSEL_MPU                  (1 << 0)
+#define RB_CM_CLKSEL_MPU_VAL           RB_CLKSEL_MPU
+#define RB_CLKSEL_DSP                  (1 << 0)
+#define RB_CLKSEL_DSP_IF               (1 << 5)
+#define RB_CM_CLKSEL_DSP_VAL           RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF
+#define RB_CLKSEL_GFX                  (1 << 0)
+#define RB_CM_CLKSEL_GFX_VAL           RB_CLKSEL_GFX
+#define RB_CLKSEL_MDM                  (1 << 0)
+#define RB_CM_CLKSEL_MDM_VAL           RB_CLKSEL_MDM
+
+/* 2420 Ratio Equivalents */
+#define RXX_CLKSEL_VLYNQ               (0x12 << 15)
+#define RXX_CLKSEL_SSI                 (0x8 << 20)
+
+/* 2420-PRCM III 532MHz core */
+#define RIII_CLKSEL_L3                 (4 << 0)        /* 133MHz */
+#define RIII_CLKSEL_L4                 (2 << 5)        /* 66.5MHz */
+#define RIII_CLKSEL_USB                        (4 << 25)       /* 33.25MHz */
+#define RIII_CM_CLKSEL1_CORE_VAL       RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \
+                                       RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \
+                                       RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \
+                                       RIII_CLKSEL_L3
+#define RIII_CLKSEL_MPU                        (2 << 0)        /* 266MHz */
+#define RIII_CM_CLKSEL_MPU_VAL         RIII_CLKSEL_MPU
+#define RIII_CLKSEL_DSP                        (3 << 0)        /* c5x - 177.3MHz */
+#define RIII_CLKSEL_DSP_IF             (2 << 5)        /* c5x - 88.67MHz */
+#define RIII_SYNC_DSP                  (1 << 7)        /* Enable sync */
+#define RIII_CLKSEL_IVA                        (6 << 8)        /* iva1 - 88.67MHz */
+#define RIII_SYNC_IVA                  (1 << 13)       /* Enable sync */
+#define RIII_CM_CLKSEL_DSP_VAL         RIII_SYNC_IVA | RIII_CLKSEL_IVA | \
+                                       RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \
+                                       RIII_CLKSEL_DSP
+#define RIII_CLKSEL_GFX                        (2 << 0)        /* 66.5MHz */
+#define RIII_CM_CLKSEL_GFX_VAL         RIII_CLKSEL_GFX
+
+/* 2420-PRCM II 600MHz core */
+#define RII_CLKSEL_L3                  (6 << 0)        /* 100MHz */
+#define RII_CLKSEL_L4                  (2 << 5)        /* 50MHz */
+#define RII_CLKSEL_USB                 (2 << 25)       /* 50MHz */
+#define RII_CM_CLKSEL1_CORE_VAL                RII_CLKSEL_USB | \
+                                       RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
+                                       RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+                                       RII_CLKSEL_L4 | RII_CLKSEL_L3
+#define RII_CLKSEL_MPU                 (2 << 0)        /* 300MHz */
+#define RII_CM_CLKSEL_MPU_VAL          RII_CLKSEL_MPU
+#define RII_CLKSEL_DSP                 (3 << 0)        /* c5x - 200MHz */
+#define RII_CLKSEL_DSP_IF              (2 << 5)        /* c5x - 100MHz */
+#define RII_SYNC_DSP                   (0 << 7)        /* Bypass sync */
+#define RII_CLKSEL_IVA                 (6 << 8)        /* iva1 - 200MHz */
+#define RII_SYNC_IVA                   (0 << 13)       /* Bypass sync */
+#define RII_CM_CLKSEL_DSP_VAL          RII_SYNC_IVA | RII_CLKSEL_IVA | \
+                                       RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \
+                                       RII_CLKSEL_DSP
+#define RII_CLKSEL_GFX                 (2 << 0)        /* 50MHz */
+#define RII_CM_CLKSEL_GFX_VAL          RII_CLKSEL_GFX
+
+/* 2420-PRCM VII (boot) */
+#define RVII_CLKSEL_L3                 (1 << 0)
+#define RVII_CLKSEL_L4                 (1 << 5)
+#define RVII_CLKSEL_DSS1               (1 << 8)
+#define RVII_CLKSEL_DSS2               (0 << 13)
+#define RVII_CLKSEL_VLYNQ              (1 << 15)
+#define RVII_CLKSEL_SSI                        (1 << 20)
+#define RVII_CLKSEL_USB                        (1 << 25)
+
+#define RVII_CM_CLKSEL1_CORE_VAL       RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \
+                                       RVII_CLKSEL_VLYNQ | RVII_CLKSEL_DSS2 | \
+                                       RVII_CLKSEL_DSS1 | RVII_CLKSEL_L4 | RVII_CLKSEL_L3
+
+#define RVII_CLKSEL_MPU                        (1 << 0) /* all divide by 1 */
+#define RVII_CM_CLKSEL_MPU_VAL         RVII_CLKSEL_MPU
+
+#define RVII_CLKSEL_DSP                        (1 << 0)
+#define RVII_CLKSEL_DSP_IF             (1 << 5)
+#define RVII_SYNC_DSP                  (0 << 7)
+#define RVII_CLKSEL_IVA                        (1 << 8)
+#define RVII_SYNC_IVA                  (0 << 13)
+#define RVII_CM_CLKSEL_DSP_VAL         RVII_SYNC_IVA | RVII_CLKSEL_IVA | RVII_SYNC_DSP | \
+                                       RVII_CLKSEL_DSP_IF | RVII_CLKSEL_DSP
+
+#define RVII_CLKSEL_GFX                        (1 << 0)
+#define RVII_CM_CLKSEL_GFX_VAL         RVII_CLKSEL_GFX
+
+/*-------------------------------------------------------------------------
+ * 2430 Target modes: Along with each configuration the CPU has several
+ * modes which goes along with them. Modes mainly are the addition of
+ * describe DPLL combinations to go along with a ratio.
+ *-------------------------------------------------------------------------*/
+
+/* Hardware governed */
+#define MX_48M_SRC                     (0 << 3)
+#define MX_54M_SRC                     (0 << 5)
+#define MX_APLLS_CLIKIN_12             (3 << 23)
+#define MX_APLLS_CLIKIN_13             (2 << 23)
+#define MX_APLLS_CLIKIN_19_2           (0 << 23)
+
+/* 
+ * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed
+ * #2  (ratio1) baseport-target
+ * #5a (ratio1) baseport-target, target DPLL = 266*2 = 532MHz
+ */
+#define M5A_DPLL_MULT_12               (133 << 12)
+#define M5A_DPLL_DIV_12                        (5 << 8)
+#define M5A_CM_CLKSEL1_PLL_12_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \
+                                       MX_APLLS_CLIKIN_12
+#define M5A_DPLL_MULT_13               (266 << 12)
+#define M5A_DPLL_DIV_13                        (12 << 8)
+#define M5A_CM_CLKSEL1_PLL_13_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \
+                                       MX_APLLS_CLIKIN_13
+#define M5A_DPLL_MULT_19               (180 << 12)
+#define M5A_DPLL_DIV_19                        (12 << 8)
+#define M5A_CM_CLKSEL1_PLL_19_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \
+                                       MX_APLLS_CLIKIN_19_2
+/* #5b (ratio1) target DPLL = 200*2 = 400MHz */
+#define M5B_DPLL_MULT_12               (50 << 12)
+#define M5B_DPLL_DIV_12                        (2 << 8)
+#define M5B_CM_CLKSEL1_PLL_12_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \
+                                       MX_APLLS_CLIKIN_12
+#define M5B_DPLL_MULT_13               (200 << 12)
+#define M5B_DPLL_DIV_13                        (12 << 8)
+
+#define M5B_CM_CLKSEL1_PLL_13_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \
+                                       MX_APLLS_CLIKIN_13
+#define M5B_DPLL_MULT_19               (125 << 12)
+#define M5B_DPLL_DIV_19                        (31 << 8)
+#define M5B_CM_CLKSEL1_PLL_19_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \
+                                       MX_APLLS_CLIKIN_19_2
+/*
+ * #4  (ratio2)
+ * #3  (ratio2) baseport-target, target DPLL = 330*2 = 660MHz
+ */
+#define M3_DPLL_MULT_12                        (55 << 12)
+#define M3_DPLL_DIV_12                 (1 << 8)
+#define M3_CM_CLKSEL1_PLL_12_VAL       MX_48M_SRC | MX_54M_SRC | \
+                                       M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \
+                                       MX_APLLS_CLIKIN_12
+#define M3_DPLL_MULT_13                        (330 << 12)
+#define M3_DPLL_DIV_13                 (12 << 8)
+#define M3_CM_CLKSEL1_PLL_13_VAL       MX_48M_SRC | MX_54M_SRC | \
+                                       M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \
+                                       MX_APLLS_CLIKIN_13
+#define M3_DPLL_MULT_19                        (275 << 12)
+#define M3_DPLL_DIV_19                 (15 << 8)
+#define M3_CM_CLKSEL1_PLL_19_VAL       MX_48M_SRC | MX_54M_SRC | \
+                                       M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \
+                                       MX_APLLS_CLIKIN_19_2
+/* boot (boot) */
+#define MB_DPLL_MULT                   (1 << 12)
+#define MB_DPLL_DIV                    (0 << 8)
+#define MB_CM_CLKSEL1_PLL_12_VAL       MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+                                       MB_DPLL_MULT | MX_APLLS_CLIKIN_12
+
+#define MB_CM_CLKSEL1_PLL_13_VAL       MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+                                       MB_DPLL_MULT | MX_APLLS_CLIKIN_13
+
+#define MB_CM_CLKSEL1_PLL_19_VAL       MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+                                       MB_DPLL_MULT | MX_APLLS_CLIKIN_19
+
+/*
+ * 2430 - chassis (sedna)
+ * 165 (ratio1) same as above #2
+ * 150 (ratio1)
+ * 133 (ratio2) same as above #4
+ * 110 (ratio2) same as above #3
+ * 104 (ratio2)
+ * boot (boot)
+ */
+
+/*
+ * 2420 Equivalent - mode registers
+ * PRCM II , target DPLL = 2*300MHz = 600MHz
+ */
+#define MII_DPLL_MULT_12               (50 << 12)
+#define MII_DPLL_DIV_12                        (1 << 8)
+#define MII_CM_CLKSEL1_PLL_12_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \
+                                       MX_APLLS_CLIKIN_12
+#define MII_DPLL_MULT_13               (300 << 12)
+#define MII_DPLL_DIV_13                        (12 << 8)
+#define MII_CM_CLKSEL1_PLL_13_VAL      MX_48M_SRC | MX_54M_SRC | \
+                                       MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \
+                                       MX_APLLS_CLIKIN_13
+
+/* PRCM III target DPLL = 2*266 = 532MHz*/
+#define MIII_DPLL_MULT_12              (133 << 12)
+#define MIII_DPLL_DIV_12               (5 << 8)
+#define MIII_CM_CLKSEL1_PLL_12_VAL     MX_48M_SRC | MX_54M_SRC | \
+                                       MIII_DPLL_DIV_12 | MIII_DPLL_MULT_12 | \
+                                       MX_APLLS_CLIKIN_12
+#define MIII_DPLL_MULT_13              (266 << 12)
+#define MIII_DPLL_DIV_13               (12 << 8)
+#define MIII_CM_CLKSEL1_PLL_13_VAL     MX_48M_SRC | MX_54M_SRC | \
+                                       MIII_DPLL_DIV_13 | MIII_DPLL_MULT_13 | \
+                                       MX_APLLS_CLIKIN_13
+
+/* PRCM VII (boot bypass) */
+#define MVII_CM_CLKSEL1_PLL_12_VAL     MB_CM_CLKSEL1_PLL_12_VAL
+#define MVII_CM_CLKSEL1_PLL_13_VAL     MB_CM_CLKSEL1_PLL_13_VAL
+
+/* High and low operation value */
+#define MX_CLKSEL2_PLL_2x_VAL          (2 << 0)
+#define MX_CLKSEL2_PLL_1x_VAL          (1 << 0)
+
+/*
+ * These represent optimal values for common parts, it won't work for all.
+ * As long as you scale down, most parameters are still work, they just
+ * become sub-optimal. The RFR value goes in the oppisite direction. If you
+ * don't adjust it down as your clock period increases the refresh interval
+ * will not be met. Setting all parameters for complete worst case may work,
+ * but may cut memory performance by 2x. Due to errata the DLLs need to be
+ * unlocked and their value needs run time calibration.        A dynamic call is
+ * need for that as no single right value exists acorss production samples.
+ *
+ * Only the FULL speed values are given. Current code is such that rate
+ * changes must be made at DPLLoutx2. The actual value adjustment for low
+ * frequency operation will be handled by omap_set_performance()
+ *
+ * By having the boot loader boot up in the fastest L4 speed available likely
+ * will result in something which you can switch between.
+ */
+#define V24XX_SDRC_RFR_CTRL_133MHz     (0x0003de00 | 1)
+#define V24XX_SDRC_RFR_CTRL_100MHz     (0x0002da01 | 1)
+#define V24XX_SDRC_RFR_CTRL_110MHz     (0x0002da01 | 1) /* Need to calc */
+#define V24XX_SDRC_RFR_CTRL_BYPASS     (0x00005000 | 1) /* Need to calc */
+
+/* MPU speed defines */
+#define S12M   12000000
+#define S13M   13000000
+#define S19M   19200000
+#define S26M   26000000
+#define S100M  100000000
+#define S133M  133000000
+#define S150M  150000000
+#define S165M  165000000
+#define S200M  200000000
+#define S266M  266000000
+#define S300M  300000000
+#define S330M  330000000
+#define S400M  400000000
+#define S532M  532000000
+#define S600M  600000000
+#define S660M  660000000
+
+/*-------------------------------------------------------------------------
+ * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+ * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
+ * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
+ * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
+ *
+ * Filling in table based on H4 boards and 2430-SDPs variants available.
+ * There are quite a few more rates combinations which could be defined.
+ *
+ * When multiple values are defiend the start up will try and choose the
+ * fastest one. If a 'fast' value is defined, then automatically, the /2
+ * one should be included as it can be used.   Generally having more that
+ * one fast set does not make sense, as static timings need to be changed
+ * to change the set.   The exception is the bypass setting which is
+ * availble for low power bypass.
+ *
+ * Note: This table needs to be sorted, fastest to slowest.
+ *-------------------------------------------------------------------------*/
+static struct prcm_config rate_table[] = {
+       /* PRCM II - FAST */
+       {S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,             /* 300MHz ARM */
+               RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+               RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+               RATE_IN_242X},
+
+       {S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,             /* 300MHz ARM */
+               RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+               RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+               RATE_IN_242X},
+
+       /* PRCM III - FAST */
+       {S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,            /* 266MHz ARM */
+               RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+               RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+               RATE_IN_242X},
+
+       {S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,            /* 266MHz ARM */
+               RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+               RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+               RATE_IN_242X},
+
+       /* PRCM II - SLOW */
+       {S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,             /* 150MHz ARM */
+               RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+               RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+               RATE_IN_242X},
+
+       {S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,             /* 150MHz ARM */
+               RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+               RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+               RATE_IN_242X},
+
+       /* PRCM III - SLOW */
+       {S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,            /* 133MHz ARM */
+               RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+               RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+               RATE_IN_242X},
+
+       {S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,            /* 133MHz ARM */
+               RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+               RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+               RATE_IN_242X},
+
+       /* PRCM-VII (boot-bypass) */
+       {S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL,              /* 12MHz ARM*/
+               RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
+               RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS,
+               RATE_IN_242X},
+
+       /* PRCM-VII (boot-bypass) */
+       {S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL,              /* 13MHz ARM */
+               RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
+               RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS,
+               RATE_IN_242X},
+
+       /* PRCM #3 - ratio2 (ES2) - FAST */
+       {S13M, S660M, S330M, R2_CM_CLKSEL_MPU_VAL,              /* 330MHz ARM */
+               R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
+               R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_110MHz,
+               RATE_IN_243X},
+
+       /* PRCM #5a - ratio1 - FAST */
+       {S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL,              /* 266MHz ARM */
+               R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+               R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_133MHz,
+               RATE_IN_243X},
+
+       /* PRCM #5b - ratio1 - FAST */
+       {S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL,              /* 200MHz ARM */
+               R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+               R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_100MHz,
+               RATE_IN_243X},
+
+       /* PRCM #3 - ratio2 (ES2) - SLOW */
+       {S13M, S330M, S165M, R2_CM_CLKSEL_MPU_VAL,              /* 165MHz ARM */
+               R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
+               R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_110MHz,
+               RATE_IN_243X},
+
+       /* PRCM #5a - ratio1 - SLOW */
+       {S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL,              /* 133MHz ARM */
+               R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+               R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_133MHz,
+               RATE_IN_243X},
+
+       /* PRCM #5b - ratio1 - SLOW*/
+       {S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL,              /* 100MHz ARM */
+               R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+               R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_100MHz,
+               RATE_IN_243X},
+
+       /* PRCM-boot/bypass */
+       {S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL,                /* 13Mhz */
+               RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
+               RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_BYPASS,
+               RATE_IN_243X},
+
+       /* PRCM-boot/bypass */
+       {S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL,                /* 12Mhz */
+               RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
+               RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL,
+               MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
+               V24XX_SDRC_RFR_CTRL_BYPASS,
+               RATE_IN_243X},
+
+       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+/*-------------------------------------------------------------------------
+ * 24xx clock tree.
+ *
+ * NOTE:In many cases here we are assigning a 'default' parent.        In many
+ *     cases the parent is selectable. The get/set parent calls will also
+ *     switch sources.
+ *
+ *     Many some clocks say always_enabled, but they can be auto idled for
+ *     power savings. They will always be available upon clock request.
+ *
+ *     Several sources are given initial rates which may be wrong, this will
+ *     be fixed up in the init func.
+ *
+ *     Things are broadly separated below by clock domains. It is
+ *     noteworthy that most periferals have dependencies on multiple clock
+ *     domains. Many get their interface clocks from the L4 domain, but get
+ *     functional clocks from fixed sources or other core domain derived
+ *     clocks.
+ *-------------------------------------------------------------------------*/
+
+/* Base external input clocks */
+static struct clk func_32k_ck = {
+       .name           = "func_32k_ck",
+       .rate           = 32000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | ALWAYS_ENABLED,
+};
+
+/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
+static struct clk osc_ck = {           /* (*12, *13, 19.2, *26, 38.4)MHz */
+       .name           = "osc_ck",
+       .rate           = 26000000,             /* fixed up in clock init */
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+/* With out modem likely 12MHz, with modem likely 13MHz */
+static struct clk sys_ck = {           /* (*12, *13, 19.2, 26, 38.4)MHz */
+       .name           = "sys_ck",             /* ~ ref_clk also */
+       .parent         = &osc_ck,
+       .rate           = 13000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+       .rate_offset    = 6, /* sysclkdiv 1 or 2, already handled or no boot */
+       .recalc         = &omap2_sys_clk_recalc,
+};
+
+static struct clk alt_ck = {           /* Typical 54M or 48M, may not exist */
+       .name           = "alt_ck",
+       .rate           = 54000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+       .recalc         = &omap2_propagate_rate,
+};
+
+/*
+ * Analog domain root source clocks
+ */
+
+/* dpll_ck, is broken out in to special cases through clksel */
+static struct clk dpll_ck = {
+       .name           = "dpll_ck",
+       .parent         = &sys_ck,              /* Can be func_32k also */
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_PROPAGATES | RATE_CKCTL | CM_PLL_SEL1,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk apll96_ck = {
+       .name           = "apll96_ck",
+       .parent         = &sys_ck,
+       .rate           = 96000000,
+       .flags          = CLOCK_IN_OMAP242X |CLOCK_IN_OMAP243X |
+                               RATE_FIXED | RATE_PROPAGATES,
+       .enable_reg     = (void __iomem *)&CM_CLKEN_PLL,
+       .enable_bit     = 0x2,
+       .recalc         = &omap2_propagate_rate,
+};
+
+static struct clk apll54_ck = {
+       .name           = "apll54_ck",
+       .parent         = &sys_ck,
+       .rate           = 54000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | RATE_PROPAGATES,
+       .enable_reg     = (void __iomem *)&CM_CLKEN_PLL,
+       .enable_bit     = 0x6,
+       .recalc         = &omap2_propagate_rate,
+};
+
+/*
+ * PRCM digital base sources
+ */
+static struct clk func_54m_ck = {
+       .name           = "func_54m_ck",
+       .parent         = &apll54_ck,   /* can also be alt_clk */
+       .rate           = 54000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES,
+       .src_offset     = 5,
+       .enable_reg     = (void __iomem *)&CM_CLKEN_PLL,
+       .enable_bit     = 0xff,
+       .recalc         = &omap2_propagate_rate,
+};
+
+static struct clk core_ck = {
+       .name           = "core_ck",
+       .parent         = &dpll_ck,             /* can also be 32k */
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               ALWAYS_ENABLED | RATE_PROPAGATES,
+       .recalc         = &omap2_propagate_rate,
+};
+
+static struct clk sleep_ck = {         /* sys_clk or 32k */
+       .name           = "sleep_ck",
+       .parent         = &func_32k_ck,
+       .rate           = 32000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .recalc         = &omap2_propagate_rate,
+};
+
+static struct clk func_96m_ck = {
+       .name           = "func_96m_ck",
+       .parent         = &apll96_ck,
+       .rate           = 96000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | RATE_PROPAGATES,
+       .enable_reg     = (void __iomem *)&CM_CLKEN_PLL,
+       .enable_bit     = 0xff,
+       .recalc         = &omap2_propagate_rate,
+};
+
+static struct clk func_48m_ck = {
+       .name           = "func_48m_ck",
+       .parent         = &apll96_ck,    /* 96M or Alt */
+       .rate           = 48000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES,
+       .src_offset     = 3,
+       .enable_reg     = (void __iomem *)&CM_CLKEN_PLL,
+       .enable_bit     = 0xff,
+       .recalc         = &omap2_propagate_rate,
+};
+
+static struct clk func_12m_ck = {
+       .name           = "func_12m_ck",
+       .parent         = &func_48m_ck,
+       .rate           = 12000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | RATE_PROPAGATES,
+       .recalc         = &omap2_propagate_rate,
+       .enable_reg     = (void __iomem *)&CM_CLKEN_PLL,
+       .enable_bit     = 0xff,
+};
+
+/* Secure timer, only available in secure mode */
+static struct clk wdt1_osc_ck = {
+       .name           = "ck_wdt1_osc",
+       .parent         = &osc_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk sys_clkout = {
+       .name           = "sys_clkout",
+       .parent         = &func_54m_ck,
+       .rate           = 54000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
+       .src_offset     = 0,
+       .enable_reg     = (void __iomem *)&PRCM_CLKOUT_CTRL,
+       .enable_bit     = 7,
+       .rate_offset    = 3,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/* In 2430, new in 2420 ES2 */
+static struct clk sys_clkout2 = {
+       .name           = "sys_clkout2",
+       .parent         = &func_54m_ck,
+       .rate           = 54000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
+       .src_offset     = 8,
+       .enable_reg     = (void __iomem *)&PRCM_CLKOUT_CTRL,
+       .enable_bit     = 15,
+       .rate_offset    = 11,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/*
+ * MPU clock domain
+ *     Clocks:
+ *             MPU_FCLK, MPU_ICLK
+ *             INT_M_FCLK, INT_M_I_CLK
+ *
+ * - Individual clocks are hardware managed.
+ * - Base divider comes from: CM_CLKSEL_MPU
+ *
+ */
+static struct clk mpu_ck = {   /* Control cpu */
+       .name           = "mpu_ck",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL |
+                               ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
+                               CONFIG_PARTICIPANT | RATE_PROPAGATES,
+       .rate_offset    = 0,    /* bits 0-4 */
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/*
+ * DSP (2430-IVA2.1) (2420-UMA+IVA1) clock domain
+ * Clocks:
+ *     2430: IVA2.1_FCLK, IVA2.1_ICLK
+ *     2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
+ */
+static struct clk iva2_1_fck = {
+       .name           = "iva2_1_fck",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+                               DELAYED_APP | RATE_PROPAGATES |
+                               CONFIG_PARTICIPANT,
+       .rate_offset    = 0,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_DSP,
+       .enable_bit     = 0,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk iva2_1_ick = {
+       .name           = "iva2_1_ick",
+       .parent         = &iva2_1_fck,
+       .flags          = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+                               DELAYED_APP | CONFIG_PARTICIPANT,
+       .rate_offset    = 5,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/*
+ * Won't be too specific here. The core clock comes into this block
+ * it is divided then tee'ed. One branch goes directly to xyz enable
+ * controls. The other branch gets further divided by 2 then possibly
+ * routed into a synchronizer and out of clocks abc.
+ */
+static struct clk dsp_fck = {
+       .name           = "dsp_fck",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+                       DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES,
+       .rate_offset    = 0,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_DSP,
+       .enable_bit     = 0,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk dsp_ick = {
+       .name           = "dsp_ick",     /* apparently ipi and isp */
+       .parent         = &dsp_fck,
+       .flags          = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+                               DELAYED_APP | CONFIG_PARTICIPANT,
+       .rate_offset = 5,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_DSP,
+       .enable_bit     = 1,            /* for ipi */
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk iva1_ifck = {
+       .name           = "iva1_ifck",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP242X | CM_DSP_SEL1 | RATE_CKCTL |
+                       CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP,
+       .rate_offset= 8,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_DSP,
+       .enable_bit     = 10,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/* IVA1 mpu/int/i/f clocks are /2 of parent */
+static struct clk iva1_mpu_int_ifck = {
+       .name           = "iva1_mpu_int_ifck",
+       .parent         = &iva1_ifck,
+       .flags          = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_DSP,
+       .enable_bit     = 8,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/*
+ * L3 clock domain
+ * L3 clocks are used for both interface and functional clocks to
+ * multiple entities. Some of these clocks are completely managed
+ * by hardware, and some others allow software control. Hardware
+ * managed ones general are based on directly CLK_REQ signals and
+ * various auto idle settings. The functional spec sets many of these
+ * as 'tie-high' for their enables.
+ *
+ * I-CLOCKS:
+ *     L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
+ *     CAM, HS-USB.
+ * F-CLOCK
+ *     SSI.
+ *
+ * GPMC memories and SDRC have timing and clock sensitive registers which
+ * may very well need notification when the clock changes. Currently for low
+ * operating points, these are taken care of in sleep.S.
+ */
+static struct clk core_l3_ck = {       /* Used for ick and fck, interconnect */
+       .name           = "core_l3_ck",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+                               DELAYED_APP | CONFIG_PARTICIPANT |
+                               RATE_PROPAGATES,
+       .rate_offset    = 0,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk usb_l4_ick = {       /* FS-USB interface clock */
+       .name           = "usb_l4_ick",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP |
+                               CONFIG_PARTICIPANT,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 0,
+       .rate_offset = 25,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/*
+ * SSI is in L3 management domain, its direct parent is core not l3,
+ * many core power domain entities are grouped into the L3 clock
+ * domain.
+ * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK
+ *
+ * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
+ */
+static struct clk ssi_ssr_sst_fck = {
+       .name           = "ssi_fck",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,     /* bit 1 */
+       .enable_bit     = 1,
+       .rate_offset = 20,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/*
+ * GFX clock domain
+ *     Clocks:
+ * GFX_FCLK, GFX_ICLK
+ * GFX_CG1(2d), GFX_CG2(3d)
+ *
+ * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
+ * The 2d and 3d clocks run at a hardware determined
+ * divided value of fclk.
+ *
+ */
+static struct clk gfx_3d_fck = {
+       .name           = "gfx_3d_fck",
+       .parent         = &core_l3_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | CM_GFX_SEL1,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_GFX,
+       .enable_bit     = 2,
+       .rate_offset= 0,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk gfx_2d_fck = {
+       .name           = "gfx_2d_fck",
+       .parent         = &core_l3_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | CM_GFX_SEL1,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_GFX,
+       .enable_bit     = 1,
+       .rate_offset= 0,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk gfx_ick = {
+       .name           = "gfx_ick",            /* From l3 */
+       .parent         = &core_l3_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_GFX,       /* bit 0 */
+       .enable_bit     = 0,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+/*
+ * Modem clock domain (2430)
+ *     CLOCKS:
+ *             MDM_OSC_CLK
+ *             MDM_ICLK
+ */
+static struct clk mdm_ick = {          /* used both as a ick and fck */
+       .name           = "mdm_ick",
+       .parent         = &core_ck,
+       .flags          = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_MODEM_SEL1 |
+                               DELAYED_APP | CONFIG_PARTICIPANT,
+       .rate_offset    = 0,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_MDM,
+       .enable_bit     = 0,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk mdm_osc_ck = {
+       .name           = "mdm_osc_ck",
+       .rate           = 26000000,
+       .parent         = &osc_ck,
+       .flags          = CLOCK_IN_OMAP243X | RATE_FIXED,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_MDM,
+       .enable_bit     = 1,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+/*
+ * L4 clock management domain
+ *
+ * This domain contains lots of interface clocks from the L4 interface, some
+ * functional clocks.  Fixed APLL functional source clocks are managed in
+ * this domain.
+ */
+static struct clk l4_ck = {            /* used both as an ick and fck */
+       .name           = "l4_ck",
+       .parent         = &core_l3_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+                               DELAYED_APP | RATE_PROPAGATES,
+       .rate_offset    = 5,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk ssi_l4_ick = {
+       .name           = "ssi_l4_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,     /* bit 1 */
+       .enable_bit     = 1,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+/*
+ * DSS clock domain
+ * CLOCKs:
+ * DSS_L4_ICLK, DSS_L3_ICLK,
+ * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
+ *
+ * DSS is both initiator and target.
+ */
+static struct clk dss_ick = {          /* Enables both L3,L4 ICLK's */
+       .name           = "dss_ick",
+       .parent         = &l4_ck,       /* really both l3 and l4 */
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 0,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk dss1_fck = {
+       .name           = "dss1_fck",
+       .parent         = &core_ck,             /* Core or sys */
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 0,
+       .rate_offset    = 8,
+       .src_offset     = 8,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk dss2_fck = {         /* Alt clk used in power management */
+       .name           = "dss2_fck",
+       .parent         = &sys_ck,              /* fixed at sys_ck or 48MHz */
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_CKCTL | CM_CORE_SEL1 | RATE_FIXED,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 1,
+       .src_offset     = 13,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk dss_54m_fck = {      /* Alt clk used in power management */
+       .name           = "dss_54m_fck",        /* 54m tv clk */
+       .parent         = &func_54m_ck,
+       .rate           = 54000000,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               RATE_FIXED | RATE_PROPAGATES,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 2,
+       .recalc         = &omap2_propagate_rate,
+};
+
+/*
+ * CORE power domain ICLK & FCLK defines.
+ * Many of the these can have more than one possible parent. Entries
+ * here will likely have an L4 interface parent, and may have multiple
+ * functional clock parents.
+ */
+static struct clk gpt1_ick = {
+       .name           = "gpt1_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_WKUP,      /* Bit4 */
+       .enable_bit     = 0,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt1_fck = {
+       .name           = "gpt1_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_WKUP_SEL1,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_WKUP,
+       .enable_bit     = 0,
+       .src_offset     = 0,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt2_ick = {
+       .name           = "gpt2_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,     /* bit4 */
+       .enable_bit     = 0,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt2_fck = {
+       .name           = "gpt2_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 4,
+       .src_offset     = 2,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt3_ick = {
+       .name           = "gpt3_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,     /* Bit5 */
+       .enable_bit     = 5,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt3_fck = {
+       .name           = "gpt3_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 5,
+       .src_offset     = 4,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt4_ick = {
+       .name           = "gpt4_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,     /* Bit6 */
+       .enable_bit     = 6,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt4_fck = {
+       .name           = "gpt4_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 6,
+       .src_offset     = 6,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt5_ick = {
+       .name           = "gpt5_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,      /* Bit7 */
+       .enable_bit     = 7,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt5_fck = {
+       .name           = "gpt5_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 7,
+       .src_offset     = 8,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt6_ick = {
+       .name           = "gpt6_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_bit     = 8,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,      /* bit8 */
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt6_fck = {
+       .name           = "gpt6_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 8,
+       .src_offset     = 10,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt7_ick = {
+       .name           = "gpt7_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,      /* bit9 */
+       .enable_bit     = 9,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt7_fck = {
+       .name           = "gpt7_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 9,
+       .src_offset     = 12,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt8_ick = {
+       .name           = "gpt8_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,      /* bit10 */
+       .enable_bit     = 10,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt8_fck = {
+       .name           = "gpt8_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 10,
+       .src_offset     = 14,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt9_ick = {
+       .name           = "gpt9_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 11,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt9_fck = {
+       .name           = "gpt9_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                                       CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 11,
+       .src_offset     = 16,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt10_ick = {
+       .name           = "gpt10_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 12,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt10_fck = {
+       .name           = "gpt10_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                                       CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 12,
+       .src_offset     = 18,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt11_ick = {
+       .name           = "gpt11_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 13,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt11_fck = {
+       .name           = "gpt11_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                                       CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 13,
+       .src_offset     = 20,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt12_ick = {
+       .name           = "gpt12_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,      /* bit14 */
+       .enable_bit     = 14,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpt12_fck = {
+       .name           = "gpt12_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                                       CM_CORE_SEL2,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 14,
+       .src_offset     = 22,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp1_ick = {
+       .name           = "mcbsp1_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_bit     = 15,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,      /* bit16 */
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp1_fck = {
+       .name           = "mcbsp1_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_bit     = 15,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp2_ick = {
+       .name           = "mcbsp2_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_bit     = 16,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp2_fck = {
+       .name           = "mcbsp2_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_bit     = 16,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp3_ick = {
+       .name           = "mcbsp3_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 3,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp3_fck = {
+       .name           = "mcbsp3_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 3,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp4_ick = {
+       .name           = "mcbsp4_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 4,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp4_fck = {
+       .name           = "mcbsp4_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 4,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp5_ick = {
+       .name           = "mcbsp5_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 5,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcbsp5_fck = {
+       .name           = "mcbsp5_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 5,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcspi1_ick = {
+       .name           = "mcspi1_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 17,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcspi1_fck = {
+       .name           = "mcspi1_fck",
+       .parent         = &func_48m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 17,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcspi2_ick = {
+       .name           = "mcspi2_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 18,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcspi2_fck = {
+       .name           = "mcspi2_fck",
+       .parent         = &func_48m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 18,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcspi3_ick = {
+       .name           = "mcspi3_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 9,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mcspi3_fck = {
+       .name           = "mcspi3_fck",
+       .parent         = &func_48m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 9,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk uart1_ick = {
+       .name           = "uart1_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 21,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk uart1_fck = {
+       .name           = "uart1_fck",
+       .parent         = &func_48m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 21,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk uart2_ick = {
+       .name           = "uart2_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 22,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk uart2_fck = {
+       .name           = "uart2_fck",
+       .parent         = &func_48m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 22,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk uart3_ick = {
+       .name           = "uart3_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 2,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk uart3_fck = {
+       .name           = "uart3_fck",
+       .parent         = &func_48m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 2,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpios_ick = {
+       .name           = "gpios_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_WKUP,
+       .enable_bit     = 2,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpios_fck = {
+       .name           = "gpios_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_WKUP,
+       .enable_bit     = 2,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mpu_wdt_ick = {
+       .name           = "mpu_wdt_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_WKUP,
+       .enable_bit     = 3,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mpu_wdt_fck = {
+       .name           = "mpu_wdt_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN_WKUP,
+       .enable_bit     = 3,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk sync_32k_ick = {
+       .name           = "sync_32k_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_WKUP,
+       .enable_bit     = 1,
+       .recalc         = &omap2_followparent_recalc,
+};
+static struct clk wdt1_ick = {
+       .name           = "wdt1_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_WKUP,
+       .enable_bit     = 4,
+       .recalc         = &omap2_followparent_recalc,
+};
+static struct clk omapctrl_ick = {
+       .name           = "omapctrl_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_WKUP,
+       .enable_bit     = 5,
+       .recalc         = &omap2_followparent_recalc,
+};
+static struct clk icr_ick = {
+       .name           = "icr_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN_WKUP,
+       .enable_bit     = 6,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk cam_ick = {
+       .name           = "cam_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 31,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk cam_fck = {
+       .name           = "cam_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 31,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mailboxes_ick = {
+       .name           = "mailboxes_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 30,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk wdt4_ick = {
+       .name           = "wdt4_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 29,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk wdt4_fck = {
+       .name           = "wdt4_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 29,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk wdt3_ick = {
+       .name           = "wdt3_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 28,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk wdt3_fck = {
+       .name           = "wdt3_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 28,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mspro_ick = {
+       .name           = "mspro_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 27,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mspro_fck = {
+       .name           = "mspro_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 27,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmc_ick = {
+       .name           = "mmc_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 26,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmc_fck = {
+       .name           = "mmc_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 26,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk fac_ick = {
+       .name           = "fac_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 25,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk fac_fck = {
+       .name           = "fac_fck",
+       .parent         = &func_12m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 25,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk eac_ick = {
+       .name           = "eac_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 24,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk eac_fck = {
+       .name           = "eac_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 24,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk hdq_ick = {
+       .name           = "hdq_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 23,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk hdq_fck = {
+       .name           = "hdq_fck",
+       .parent         = &func_12m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 23,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk i2c2_ick = {
+       .name           = "i2c2_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 20,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk i2c2_fck = {
+       .name           = "i2c2_fck",
+       .parent         = &func_12m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 20,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk i2chs2_fck = {
+       .name           = "i2chs2_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 20,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk i2c1_ick = {
+       .name           = "i2c1_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 19,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk i2c1_fck = {
+       .name           = "i2c1_fck",
+       .parent         = &func_12m_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 19,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk i2chs1_fck = {
+       .name           = "i2chs1_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 19,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk vlynq_ick = {
+       .name           = "vlynq_ick",
+       .parent         = &core_l3_ck,
+       .flags          = CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN1_CORE,
+       .enable_bit     = 3,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk vlynq_fck = {
+       .name           = "vlynq_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP242X  | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN1_CORE,
+       .enable_bit     = 3,
+       .src_offset     = 15,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk sdrc_ick = {
+       .name           = "sdrc_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN3_CORE,
+       .enable_bit     = 2,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk des_ick = {
+       .name           = "des_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN4_CORE,
+       .enable_bit     = 0,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk sha_ick = {
+       .name           = "sha_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN4_CORE,
+       .enable_bit     = 1,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk rng_ick = {
+       .name           = "rng_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN4_CORE,
+       .enable_bit     = 2,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk aes_ick = {
+       .name           = "aes_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN4_CORE,
+       .enable_bit     = 3,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk pka_ick = {
+       .name           = "pka_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN4_CORE,
+       .enable_bit     = 4,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk usb_fck = {
+       .name           = "usb_fck",
+       .parent         = &func_48m_ck,
+       .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 0,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk usbhs_ick = {
+       .name           = "usbhs_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 6,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmchs1_ick = {
+       .name           = "mmchs1_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 7,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmchs1_fck = {
+       .name           = "mmchs1_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 7,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmchs2_ick = {
+       .name           = "mmchs2_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 8,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmchs2_fck = {
+       .name           = "mmchs2_fck",
+       .parent         = &func_96m_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 8,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpio5_ick = {
+       .name           = "gpio5_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 10,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk gpio5_fck = {
+       .name           = "gpio5_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 10,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mdm_intc_ick = {
+       .name           = "mdm_intc_ick",
+       .parent         = &l4_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_ICLKEN2_CORE,
+       .enable_bit     = 11,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmchsdb1_fck = {
+       .name           = "mmchsdb1_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 16,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+static struct clk mmchsdb2_fck = {
+       .name           = "mmchsdb2_fck",
+       .parent         = &func_32k_ck,
+       .flags          = CLOCK_IN_OMAP243X,
+       .enable_reg     = (void __iomem *)&CM_FCLKEN2_CORE,
+       .enable_bit     = 17,
+       .recalc         = &omap2_followparent_recalc,
+};
+
+/*
+ * This clock is a composite clock which does entire set changes then
+ * forces a rebalance. It keys on the MPU speed, but it really could
+ * be any key speed part of a set in the rate table.
+ *
+ * to really change a set, you need memory table sets which get changed
+ * in sram, pre-notifiers & post notifiers, changing the top set, without
+ * having low level display recalc's won't work... this is why dpm notifiers
+ * work, isr's off, walk a list of clocks already _off_ and not messing with
+ * the bus.
+ *
+ * This clock should have no parent. It embodies the entire upper level
+ * active set. A parent will mess up some of the init also.
+ */
+static struct clk virt_prcm_set = {
+       .name           = "virt_prcm_set",
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
+       .parent         = &mpu_ck,      /* Indexed by mpu speed, no parent */
+       .recalc         = &omap2_mpu_recalc,    /* sets are keyed on mpu rate */
+       .set_rate       = &omap2_select_table_rate,
+       .round_rate     = &omap2_round_to_table_rate,
+};
+
+static struct clk *onchip_clks[] = {
+       /* external root sources */
+       &func_32k_ck,
+       &osc_ck,
+       &sys_ck,
+       &alt_ck,
+       /* internal analog sources */
+       &dpll_ck,
+       &apll96_ck,
+       &apll54_ck,
+       /* internal prcm root sources */
+       &func_54m_ck,
+       &core_ck,
+       &sleep_ck,
+       &func_96m_ck,
+       &func_48m_ck,
+       &func_12m_ck,
+       &wdt1_osc_ck,
+       &sys_clkout,
+       &sys_clkout2,
+       /* mpu domain clocks */
+       &mpu_ck,
+       /* dsp domain clocks */
+       &iva2_1_fck,            /* 2430 */
+       &iva2_1_ick,
+       &dsp_ick,               /* 2420 */
+       &dsp_fck,
+       &iva1_ifck,
+       &iva1_mpu_int_ifck,
+       /* GFX domain clocks */
+       &gfx_3d_fck,
+       &gfx_2d_fck,
+       &gfx_ick,
+       /* Modem domain clocks */
+       &mdm_ick,
+       &mdm_osc_ck,
+       /* DSS domain clocks */
+       &dss_ick,
+       &dss1_fck,
+       &dss2_fck,
+       &dss_54m_fck,
+       /* L3 domain clocks */
+       &core_l3_ck,
+       &ssi_ssr_sst_fck,
+       &usb_l4_ick,
+       /* L4 domain clocks */
+       &l4_ck,                 /* used as both core_l4 and wu_l4 */
+       &ssi_l4_ick,
+       /* virtual meta-group clock */
+       &virt_prcm_set,
+       /* general l4 interface ck, multi-parent functional clk */
+       &gpt1_ick,
+       &gpt1_fck,
+       &gpt2_ick,
+       &gpt2_fck,
+       &gpt3_ick,
+       &gpt3_fck,
+       &gpt4_ick,
+       &gpt4_fck,
+       &gpt5_ick,
+       &gpt5_fck,
+       &gpt6_ick,
+       &gpt6_fck,
+       &gpt7_ick,
+       &gpt7_fck,
+       &gpt8_ick,
+       &gpt8_fck,
+       &gpt9_ick,
+       &gpt9_fck,
+       &gpt10_ick,
+       &gpt10_fck,
+       &gpt11_ick,
+       &gpt11_fck,
+       &gpt12_ick,
+       &gpt12_fck,
+       &mcbsp1_ick,
+       &mcbsp1_fck,
+       &mcbsp2_ick,
+       &mcbsp2_fck,
+       &mcbsp3_ick,
+       &mcbsp3_fck,
+       &mcbsp4_ick,
+       &mcbsp4_fck,
+       &mcbsp5_ick,
+       &mcbsp5_fck,
+       &mcspi1_ick,
+       &mcspi1_fck,
+       &mcspi2_ick,
+       &mcspi2_fck,
+       &mcspi3_ick,
+       &mcspi3_fck,
+       &uart1_ick,
+       &uart1_fck,
+       &uart2_ick,
+       &uart2_fck,
+       &uart3_ick,
+       &uart3_fck,
+       &gpios_ick,
+       &gpios_fck,
+       &mpu_wdt_ick,
+       &mpu_wdt_fck,
+       &sync_32k_ick,
+       &wdt1_ick,
+       &omapctrl_ick,
+       &icr_ick,
+       &cam_fck,
+       &cam_ick,
+       &mailboxes_ick,
+       &wdt4_ick,
+       &wdt4_fck,
+       &wdt3_ick,
+       &wdt3_fck,
+       &mspro_ick,
+       &mspro_fck,
+       &mmc_ick,
+       &mmc_fck,
+       &fac_ick,
+       &fac_fck,
+       &eac_ick,
+       &eac_fck,
+       &hdq_ick,
+       &hdq_fck,
+       &i2c1_ick,
+       &i2c1_fck,
+       &i2chs1_fck,
+       &i2c2_ick,
+       &i2c2_fck,
+       &i2chs2_fck,
+       &vlynq_ick,
+       &vlynq_fck,
+       &sdrc_ick,
+       &des_ick,
+       &sha_ick,
+       &rng_ick,
+       &aes_ick,
+       &pka_ick,
+       &usb_fck,
+       &usbhs_ick,
+       &mmchs1_ick,
+       &mmchs1_fck,
+       &mmchs2_ick,
+       &mmchs2_fck,
+       &gpio5_ick,
+       &gpio5_fck,
+       &mdm_intc_ick,
+       &mmchsdb1_fck,
+       &mmchsdb2_fck,
+};
+
+#endif
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
new file mode 100644 (file)
index 0000000..7181edb
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/arm/mach-omap2/devices.c
+ *
+ * OMAP2 platform device setup/initialization
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/tc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
+
+extern void omap_nop_release(struct device *dev);
+
+/*-------------------------------------------------------------------------*/
+
+#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+
+#define OMAP2_I2C_BASE2                0x48072000
+#define OMAP2_I2C_INT2         57
+
+static struct resource i2c_resources2[] = {
+       {
+               .start          = OMAP2_I2C_BASE2,
+               .end            = OMAP2_I2C_BASE2 + 0x3f,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = OMAP2_I2C_INT2,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device omap_i2c_device2 = {
+        .name           = "i2c_omap",
+        .id             = 2,
+        .dev = {
+                .release        = omap_nop_release,
+        },
+       .num_resources  = ARRAY_SIZE(i2c_resources2),
+       .resource       = i2c_resources2,
+};
+
+/* See also arch/arm/plat-omap/devices.c for first I2C on 24xx */
+static void omap_init_i2c(void)
+{
+       /* REVISIT: Second I2C not in use on H4? */
+       if (machine_is_omap_h4())
+               return;
+
+       omap_cfg_reg(J15_24XX_I2C2_SCL);
+       omap_cfg_reg(H19_24XX_I2C2_SDA);
+       (void) platform_device_register(&omap_i2c_device2);
+}
+
+#else
+
+static void omap_init_i2c(void) {}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static int __init omap2_init_devices(void)
+{
+       /* please keep these calls, and their implementations above,
+        * in alphabetical order so they're easier to sort through.
+        */
+       omap_init_i2c();
+
+       return 0;
+}
+arch_initcall(omap2_init_devices);
+
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
new file mode 100644 (file)
index 0000000..7618730
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/arm/mach-omap2/id.c
+ *
+ * OMAP2 CPU identification code
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define OMAP24XX_TAP_BASE      io_p2v(0x48014000)
+
+#define OMAP_TAP_IDCODE                0x0204
+#define OMAP_TAP_PROD_ID       0x0208
+
+#define OMAP_TAP_DIE_ID_0      0x0218
+#define OMAP_TAP_DIE_ID_1      0x021C
+#define OMAP_TAP_DIE_ID_2      0x0220
+#define OMAP_TAP_DIE_ID_3      0x0224
+
+/* system_rev fields for OMAP2 processors:
+ *   CPU id bits     [31:16],
+ *   CPU device type [15:12], (unprg,normal,POP)
+ *   CPU revision    [11:08]
+ *   CPU class bits  [07:00]
+ */
+
+struct omap_id {
+       u16     hawkeye;        /* Silicon type (Hawkeye id) */
+       u8      dev;            /* Device type from production_id reg */
+       u32     type;           /* combined type id copied to system_rev */
+};
+
+/* Register values to detect the OMAP version */
+static struct omap_id omap_ids[] __initdata = {
+       { .hawkeye = 0xb5d9, .dev = 0x0, .type = 0x24200000 },
+       { .hawkeye = 0xb5d9, .dev = 0x1, .type = 0x24201000 },
+       { .hawkeye = 0xb5d9, .dev = 0x2, .type = 0x24202000 },
+       { .hawkeye = 0xb5d9, .dev = 0x4, .type = 0x24220000 },
+       { .hawkeye = 0xb5d9, .dev = 0x8, .type = 0x24230000 },
+       { .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300000 },
+};
+
+static u32 __init read_tap_reg(int reg)
+{
+       return __raw_readl(OMAP24XX_TAP_BASE + reg);
+}
+
+void __init omap2_check_revision(void)
+{
+       int i, j;
+       u32 idcode;
+       u32 prod_id;
+       u16 hawkeye;
+       u8  dev_type;
+       u8  rev;
+
+       idcode = read_tap_reg(OMAP_TAP_IDCODE);
+       prod_id = read_tap_reg(OMAP_TAP_PROD_ID);
+       hawkeye = (idcode >> 12) & 0xffff;
+       rev = (idcode >> 28) & 0x0f;
+       dev_type = (prod_id >> 16) & 0x0f;
+
+#ifdef DEBUG
+       printk(KERN_DEBUG "OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n",
+               idcode, rev, hawkeye, (idcode >> 1) & 0x7ff);
+       printk(KERN_DEBUG "OMAP_TAP_DIE_ID_0: 0x%08x\n",
+               read_tap_reg(OMAP_TAP_DIE_ID_0));
+       printk(KERN_DEBUG "OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n",
+               read_tap_reg(OMAP_TAP_DIE_ID_1),
+              (read_tap_reg(OMAP_TAP_DIE_ID_1) >> 28) & 0xf);
+       printk(KERN_DEBUG "OMAP_TAP_DIE_ID_2: 0x%08x\n",
+               read_tap_reg(OMAP_TAP_DIE_ID_2));
+       printk(KERN_DEBUG "OMAP_TAP_DIE_ID_3: 0x%08x\n",
+               read_tap_reg(OMAP_TAP_DIE_ID_3));
+       printk(KERN_DEBUG "OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n",
+               prod_id, dev_type);
+#endif
+
+       /* Check hawkeye ids */
+       for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+               if (hawkeye == omap_ids[i].hawkeye)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(omap_ids)) {
+               printk(KERN_ERR "Unknown OMAP CPU id\n");
+               return;
+       }
+
+       for (j = i; j < ARRAY_SIZE(omap_ids); j++) {
+               if (dev_type == omap_ids[j].dev)
+                       break;
+       }
+
+       if (j == ARRAY_SIZE(omap_ids)) {
+               printk(KERN_ERR "Unknown OMAP device type. "
+                               "Handling it as OMAP%04x\n",
+                               omap_ids[i].type >> 16);
+               j = i;
+       }
+       system_rev = omap_ids[j].type;
+
+       system_rev |= rev << 8;
+
+       /* Add the cpu class info (24xx) */
+       system_rev |= 0x24;
+
+       pr_info("OMAP%04x", system_rev >> 16);
+       if ((system_rev >> 8) & 0x0f)
+               printk("%x", (system_rev >> 8) & 0x0f);
+       printk("\n");
+}
+
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
new file mode 100644 (file)
index 0000000..99492c6
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-omap2/io.c
+ *
+ * OMAP2 I/O mapping code
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+#include <asm/io.h>
+#include <asm/arch/mux.h>
+
+extern void omap_sram_init(void);
+extern int omap2_clk_init(void);
+extern void omap2_check_revision(void);
+
+/*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+ */
+static struct map_desc omap2_io_desc[] __initdata = {
+       { L3_24XX_VIRT, L3_24XX_PHYS,   L3_24XX_SIZE,   MT_DEVICE },
+       { L4_24XX_VIRT, L4_24XX_PHYS,   L4_24XX_SIZE,   MT_DEVICE },
+};
+
+void __init omap_map_common_io(void)
+{
+       iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+       omap2_check_revision();
+       omap_sram_init();
+       omap2_mux_init();
+       omap2_clk_init();
+}
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
new file mode 100644 (file)
index 0000000..d7baff6
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/irq.c
+ *
+ * Interrupt handler for OMAP2 boards.
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <asm/hardware.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#define INTC_REVISION  0x0000
+#define INTC_SYSCONFIG 0x0010
+#define INTC_SYSSTATUS 0x0014
+#define INTC_CONTROL   0x0048
+#define INTC_MIR_CLEAR0        0x0088
+#define INTC_MIR_SET0  0x008c
+
+/*
+ * OMAP2 has a number of different interrupt controllers, each interrupt
+ * controller is identified as its own "bank". Register definitions are
+ * fairly consistent for each bank, but not all registers are implemented
+ * for each bank.. when in doubt, consult the TRM.
+ */
+static struct omap_irq_bank {
+       unsigned long base_reg;
+       unsigned int nr_irqs;
+} __attribute__ ((aligned(4))) irq_banks[] = {
+       {
+               /* MPU INTC */
+               .base_reg       = OMAP24XX_IC_BASE,
+               .nr_irqs        = 96,
+       }, {
+               /* XXX: DSP INTC */
+
+#if 0
+       /*
+        * Commented out for now until we fix the IVA clocking
+        */
+#ifdef CONFIG_ARCH_OMAP2420
+       }, {
+               /* IVA INTC (2420 only) */
+               .base_reg       = OMAP24XX_IVA_INTC_BASE,
+               .nr_irqs        = 16,   /* Actually 32, but only 16 are used */
+#endif
+#endif
+       }
+};
+
+/* XXX: FIQ and additional INTC support (only MPU at the moment) */
+static void omap_ack_irq(unsigned int irq)
+{
+       omap_writel(0x1, irq_banks[0].base_reg + INTC_CONTROL);
+}
+
+static void omap_mask_irq(unsigned int irq)
+{
+       int offset = (irq >> 5) << 5;
+
+       if (irq >= 64) {
+               irq %= 64;
+       } else if (irq >= 32) {
+               irq %= 32;
+       }
+
+       omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset);
+}
+
+static void omap_unmask_irq(unsigned int irq)
+{
+       int offset = (irq >> 5) << 5;
+
+       if (irq >= 64) {
+               irq %= 64;
+       } else if (irq >= 32) {
+               irq %= 32;
+       }
+
+       omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_CLEAR0 + offset);
+}
+
+static void omap_mask_ack_irq(unsigned int irq)
+{
+       omap_mask_irq(irq);
+       omap_ack_irq(irq);
+}
+
+static struct irqchip omap_irq_chip = {
+       .ack    = omap_mask_ack_irq,
+       .mask   = omap_mask_irq,
+       .unmask = omap_unmask_irq,
+};
+
+static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
+{
+       unsigned long tmp;
+
+       tmp = omap_readl(bank->base_reg + INTC_REVISION) & 0xff;
+       printk(KERN_INFO "IRQ: Found an INTC at 0x%08lx "
+                        "(revision %ld.%ld) with %d interrupts\n",
+                        bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
+
+       tmp = omap_readl(bank->base_reg + INTC_SYSCONFIG);
+       tmp |= 1 << 1;  /* soft reset */
+       omap_writel(tmp, bank->base_reg + INTC_SYSCONFIG);
+
+       while (!(omap_readl(bank->base_reg + INTC_SYSSTATUS) & 0x1))
+               /* Wait for reset to complete */;
+}
+
+void __init omap_init_irq(void)
+{
+       unsigned long nr_irqs = 0;
+       unsigned int nr_banks = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
+               struct omap_irq_bank *bank = irq_banks + i;
+
+               /* XXX */
+               if (!bank->base_reg)
+                       continue;
+
+               omap_irq_bank_init_one(bank);
+
+               nr_irqs += bank->nr_irqs;
+               nr_banks++;
+       }
+
+       printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n",
+              nr_irqs, nr_banks, nr_banks > 1 ? "s" : "");
+
+       for (i = 0; i < nr_irqs; i++) {
+               set_irq_chip(i, &omap_irq_chip);
+               set_irq_handler(i, do_level_IRQ);
+               set_irq_flags(i, IRQF_VALID);
+       }
+}
+
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
new file mode 100644 (file)
index 0000000..ea46548
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * linux/arch/arm/mach-omap2/mux.c
+ *
+ * OMAP1 pin multiplexing configurations
+ *
+ * Copyright (C) 2003 - 2005 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>
+
+#include <asm/arch/mux.h>
+
+#ifdef CONFIG_OMAP_MUX
+
+/* NOTE: See mux.h for the enumeration */
+
+struct pin_config __initdata_or_module omap24xx_pins[] = {
+/*
+ *     description                     mux     mux     pull    pull    debug
+ *                                     offset  mode    ena     type
+ */
+
+/* 24xx I2C */
+MUX_CFG_24XX("M19_24XX_I2C1_SCL",      0x111,  0,      0,      0,      1)
+MUX_CFG_24XX("L15_24XX_I2C1_SDA",      0x112,  0,      0,      0,      1)
+MUX_CFG_24XX("J15_24XX_I2C2_SCL",      0x113,  0,      0,      0,      1)
+MUX_CFG_24XX("H19_24XX_I2C2_SDA",      0x114,  0,      0,      0,      1)
+
+/* Menelaus interrupt */
+MUX_CFG_24XX("W19_24XX_SYS_NIRQ",      0x12c,  0,      1,      1,      1)
+
+/* 24xx GPIO */
+MUX_CFG_24XX("Y20_24XX_GPIO60",                0x12c,  3,      0,      0,      1)
+MUX_CFG_24XX("M15_24XX_GPIO92",                0x10a,  3,      0,      0,      1)
+
+};
+
+int __init omap2_mux_init(void)
+{
+       omap_mux_register(omap24xx_pins, ARRAY_SIZE(omap24xx_pins));
+       return 0;
+}
+
+#endif
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm.h
new file mode 100644 (file)
index 0000000..2eb89b9
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * prcm.h - Access definations for use in OMAP24XX clock and power management
+ *
+ * Copyright (C) 2005 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
+ */
+
+#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
+#define __ASM_ARM_ARCH_DPM_PRCM_H
+
+/* SET_PERFORMANCE_LEVEL PARAMETERS */
+#define PRCM_HALF_SPEED 1
+#define PRCM_FULL_SPEED 2
+
+#ifndef __ASSEMBLER__
+
+#define PRCM_REG32(offset)     __REG32(OMAP24XX_PRCM_BASE + (offset))
+
+#define PRCM_REVISION          PRCM_REG32(0x000)
+#define PRCM_SYSCONFIG         PRCM_REG32(0x010)
+#define PRCM_IRQSTATUS_MPU     PRCM_REG32(0x018)
+#define PRCM_IRQENABLE_MPU     PRCM_REG32(0x01C)
+#define PRCM_VOLTCTRL          PRCM_REG32(0x050)
+#define PRCM_VOLTST            PRCM_REG32(0x054)
+#define PRCM_CLKSRC_CTRL       PRCM_REG32(0x060)
+#define PRCM_CLKOUT_CTRL       PRCM_REG32(0x070)
+#define PRCM_CLKEMUL_CTRL      PRCM_REG32(0x078)
+#define PRCM_CLKCFG_CTRL       PRCM_REG32(0x080)
+#define PRCM_CLKCFG_STATUS     PRCM_REG32(0x084)
+#define PRCM_VOLTSETUP         PRCM_REG32(0x090)
+#define PRCM_CLKSSETUP         PRCM_REG32(0x094)
+#define PRCM_POLCTRL           PRCM_REG32(0x098)
+
+/* GENERAL PURPOSE */
+#define GENERAL_PURPOSE1       PRCM_REG32(0x0B0)
+#define GENERAL_PURPOSE2       PRCM_REG32(0x0B4)
+#define GENERAL_PURPOSE3       PRCM_REG32(0x0B8)
+#define GENERAL_PURPOSE4       PRCM_REG32(0x0BC)
+#define GENERAL_PURPOSE5       PRCM_REG32(0x0C0)
+#define GENERAL_PURPOSE6       PRCM_REG32(0x0C4)
+#define GENERAL_PURPOSE7       PRCM_REG32(0x0C8)
+#define GENERAL_PURPOSE8       PRCM_REG32(0x0CC)
+#define GENERAL_PURPOSE9       PRCM_REG32(0x0D0)
+#define GENERAL_PURPOSE10      PRCM_REG32(0x0D4)
+#define GENERAL_PURPOSE11      PRCM_REG32(0x0D8)
+#define GENERAL_PURPOSE12      PRCM_REG32(0x0DC)
+#define GENERAL_PURPOSE13      PRCM_REG32(0x0E0)
+#define GENERAL_PURPOSE14      PRCM_REG32(0x0E4)
+#define GENERAL_PURPOSE15      PRCM_REG32(0x0E8)
+#define GENERAL_PURPOSE16      PRCM_REG32(0x0EC)
+#define GENERAL_PURPOSE17      PRCM_REG32(0x0F0)
+#define GENERAL_PURPOSE18      PRCM_REG32(0x0F4)
+#define GENERAL_PURPOSE19      PRCM_REG32(0x0F8)
+#define GENERAL_PURPOSE20      PRCM_REG32(0x0FC)
+
+/* MPU */
+#define CM_CLKSEL_MPU          PRCM_REG32(0x140)
+#define CM_CLKSTCTRL_MPU       PRCM_REG32(0x148)
+#define RM_RSTST_MPU           PRCM_REG32(0x158)
+#define PM_WKDEP_MPU           PRCM_REG32(0x1C8)
+#define PM_EVGENCTRL_MPU       PRCM_REG32(0x1D4)
+#define PM_EVEGENONTIM_MPU     PRCM_REG32(0x1D8)
+#define PM_EVEGENOFFTIM_MPU    PRCM_REG32(0x1DC)
+#define PM_PWSTCTRL_MPU                PRCM_REG32(0x1E0)
+#define PM_PWSTST_MPU          PRCM_REG32(0x1E4)
+
+/* CORE */
+#define CM_FCLKEN1_CORE                PRCM_REG32(0x200)
+#define CM_FCLKEN2_CORE                PRCM_REG32(0x204)
+#define CM_FCLKEN3_CORE                PRCM_REG32(0x208)
+#define CM_ICLKEN1_CORE                PRCM_REG32(0x210)
+#define CM_ICLKEN2_CORE                PRCM_REG32(0x214)
+#define CM_ICLKEN3_CORE                PRCM_REG32(0x218)
+#define CM_ICLKEN4_CORE                PRCM_REG32(0x21C)
+#define CM_IDLEST1_CORE                PRCM_REG32(0x220)
+#define CM_IDLEST2_CORE                PRCM_REG32(0x224)
+#define CM_IDLEST3_CORE                PRCM_REG32(0x228)
+#define CM_IDLEST4_CORE                PRCM_REG32(0x22C)
+#define CM_AUTOIDLE1_CORE      PRCM_REG32(0x230)
+#define CM_AUTOIDLE2_CORE      PRCM_REG32(0x234)
+#define CM_AUTOIDLE3_CORE      PRCM_REG32(0x238)
+#define CM_AUTOIDLE4_CORE      PRCM_REG32(0x23C)
+#define CM_CLKSEL1_CORE                PRCM_REG32(0x240)
+#define CM_CLKSEL2_CORE                PRCM_REG32(0x244)
+#define CM_CLKSTCTRL_CORE      PRCM_REG32(0x248)
+#define PM_WKEN1_CORE          PRCM_REG32(0x2A0)
+#define PM_WKEN2_CORE          PRCM_REG32(0x2A4)
+#define PM_WKST1_CORE          PRCM_REG32(0x2B0)
+#define PM_WKST2_CORE          PRCM_REG32(0x2B4)
+#define PM_WKDEP_CORE          PRCM_REG32(0x2C8)
+#define PM_PWSTCTRL_CORE       PRCM_REG32(0x2E0)
+#define PM_PWSTST_CORE         PRCM_REG32(0x2E4)
+
+/* GFX */
+#define CM_FCLKEN_GFX          PRCM_REG32(0x300)
+#define CM_ICLKEN_GFX          PRCM_REG32(0x310)
+#define CM_IDLEST_GFX          PRCM_REG32(0x320)
+#define CM_CLKSEL_GFX          PRCM_REG32(0x340)
+#define CM_CLKSTCTRL_GFX       PRCM_REG32(0x348)
+#define RM_RSTCTRL_GFX         PRCM_REG32(0x350)
+#define RM_RSTST_GFX           PRCM_REG32(0x358)
+#define PM_WKDEP_GFX           PRCM_REG32(0x3C8)
+#define PM_PWSTCTRL_GFX                PRCM_REG32(0x3E0)
+#define PM_PWSTST_GFX          PRCM_REG32(0x3E4)
+
+/* WAKE-UP */
+#define CM_FCLKEN_WKUP         PRCM_REG32(0x400)
+#define CM_ICLKEN_WKUP         PRCM_REG32(0x410)
+#define CM_IDLEST_WKUP         PRCM_REG32(0x420)
+#define CM_AUTOIDLE_WKUP       PRCM_REG32(0x430)
+#define CM_CLKSEL_WKUP         PRCM_REG32(0x440)
+#define RM_RSTCTRL_WKUP                PRCM_REG32(0x450)
+#define RM_RSTTIME_WKUP                PRCM_REG32(0x454)
+#define RM_RSTST_WKUP          PRCM_REG32(0x458)
+#define PM_WKEN_WKUP           PRCM_REG32(0x4A0)
+#define PM_WKST_WKUP           PRCM_REG32(0x4B0)
+
+/* CLOCKS */
+#define CM_CLKEN_PLL           PRCM_REG32(0x500)
+#define CM_IDLEST_CKGEN                PRCM_REG32(0x520)
+#define CM_AUTOIDLE_PLL                PRCM_REG32(0x530)
+#define CM_CLKSEL1_PLL         PRCM_REG32(0x540)
+#define CM_CLKSEL2_PLL         PRCM_REG32(0x544)
+
+/* DSP */
+#define CM_FCLKEN_DSP          PRCM_REG32(0x800)
+#define CM_ICLKEN_DSP          PRCM_REG32(0x810)
+#define CM_IDLEST_DSP          PRCM_REG32(0x820)
+#define CM_AUTOIDLE_DSP                PRCM_REG32(0x830)
+#define CM_CLKSEL_DSP          PRCM_REG32(0x840)
+#define CM_CLKSTCTRL_DSP       PRCM_REG32(0x848)
+#define RM_RSTCTRL_DSP         PRCM_REG32(0x850)
+#define RM_RSTST_DSP           PRCM_REG32(0x858)
+#define PM_WKEN_DSP            PRCM_REG32(0x8A0)
+#define PM_WKDEP_DSP           PRCM_REG32(0x8C8)
+#define PM_PWSTCTRL_DSP                PRCM_REG32(0x8E0)
+#define PM_PWSTST_DSP          PRCM_REG32(0x8E4)
+#define PRCM_IRQSTATUS_DSP     PRCM_REG32(0x8F0)
+#define PRCM_IRQENABLE_DSP     PRCM_REG32(0x8F4)
+
+/* IVA */
+#define PRCM_IRQSTATUS_IVA     PRCM_REG32(0x8F8)
+#define PRCM_IRQENABLE_IVA     PRCM_REG32(0x8FC)
+
+/* Modem on 2430 */
+#define CM_FCLKEN_MDM          PRCM_REG32(0xC00)
+#define CM_ICLKEN_MDM          PRCM_REG32(0xC10)
+#define CM_IDLEST_MDM          PRCM_REG32(0xC20)
+#define CM_CLKSEL_MDM          PRCM_REG32(0xC40)
+
+/* FIXME: Move to header for 2430 */
+#define DISP_BASE              (OMAP24XX_L4_IO_BASE+0x50000)
+#define DISP_REG32(offset)     __REG32(DISP_BASE + (offset))
+
+#define GPMC_BASE              (OMAP24XX_GPMC_BASE)
+#define GPMC_REG32(offset)     __REG32(GPMC_BASE + (offset))
+
+#define GPT1_BASE              (OMAP24XX_GPT1)
+#define GPT1_REG32(offset)     __REG32(GPT1_BASE + (offset))
+
+/* Misc sysconfig */
+#define DISPC_SYSCONFIG                DISP_REG32(0x410)
+#define SPI_BASE               (OMAP24XX_L4_IO_BASE+0x98000)
+#define MCSPI1_SYSCONFIG       __REG32(SPI_BASE + 0x10)
+#define MCSPI2_SYSCONFIG       __REG32(SPI_BASE+0x2000 + 0x10)
+
+//#define DSP_MMU_SYSCONFIG    0x5A000010
+#define CAMERA_MMU_SYSCONFIG   __REG32(DISP_BASE+0x2C10)
+//#define IVA_MMU_SYSCONFIG    0x5D000010
+//#define DSP_DMA_SYSCONFIG    0x00FCC02C
+#define CAMERA_DMA_SYSCONFIG   __REG32(DISP_BASE+0x282C)
+#define SYSTEM_DMA_SYSCONFIG   __REG32(DISP_BASE+0x602C)
+#define GPMC_SYSCONFIG         GPMC_REG32(0x010)
+#define MAILBOXES_SYSCONFIG    __REG32(OMAP24XX_L4_IO_BASE+0x94010)
+#define UART1_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
+#define UART2_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
+#define UART3_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
+//#define IVA_SYSCONFIG                0x5C060010
+#define SDRC_SYSCONFIG         __REG32(OMAP24XX_SDRC_BASE+0x10)
+#define SMS_SYSCONFIG          __REG32(OMAP24XX_SMS_BASE+0x10)
+#define SSI_SYSCONFIG          __REG32(DISP_BASE+0x8010)
+//#define VLYNQ_SYSCONFIG      0x67FFFE10
+
+/* rkw - good cannidates for PM_ to start what nm was trying */
+#define OMAP24XX_GPT2          (OMAP24XX_L4_IO_BASE+0x2A000)
+#define OMAP24XX_GPT3          (OMAP24XX_L4_IO_BASE+0x78000)
+#define OMAP24XX_GPT4          (OMAP24XX_L4_IO_BASE+0x7A000)
+#define OMAP24XX_GPT5          (OMAP24XX_L4_IO_BASE+0x7C000)
+#define OMAP24XX_GPT6          (OMAP24XX_L4_IO_BASE+0x7E000)
+#define OMAP24XX_GPT7          (OMAP24XX_L4_IO_BASE+0x80000)
+#define OMAP24XX_GPT8          (OMAP24XX_L4_IO_BASE+0x82000)
+#define OMAP24XX_GPT9          (OMAP24XX_L4_IO_BASE+0x84000)
+#define OMAP24XX_GPT10         (OMAP24XX_L4_IO_BASE+0x86000)
+#define OMAP24XX_GPT11         (OMAP24XX_L4_IO_BASE+0x88000)
+#define OMAP24XX_GPT12         (OMAP24XX_L4_IO_BASE+0x8A000)
+
+#define GPTIMER1_SYSCONFIG     GPT1_REG32(0x010)
+#define GPTIMER2_SYSCONFIG     __REG32(OMAP24XX_GPT2 + 0x10)
+#define GPTIMER3_SYSCONFIG     __REG32(OMAP24XX_GPT3 + 0x10)
+#define GPTIMER4_SYSCONFIG     __REG32(OMAP24XX_GPT4 + 0x10)
+#define GPTIMER5_SYSCONFIG     __REG32(OMAP24XX_GPT5 + 0x10)
+#define GPTIMER6_SYSCONFIG     __REG32(OMAP24XX_GPT6 + 0x10)
+#define GPTIMER7_SYSCONFIG     __REG32(OMAP24XX_GPT7 + 0x10)
+#define GPTIMER8_SYSCONFIG     __REG32(OMAP24XX_GPT8 + 0x10)
+#define GPTIMER9_SYSCONFIG     __REG32(OMAP24XX_GPT9 + 0x10)
+#define GPTIMER10_SYSCONFIG    __REG32(OMAP24XX_GPT10 + 0x10)
+#define GPTIMER11_SYSCONFIG    __REG32(OMAP24XX_GPT11 + 0x10)
+#define GPTIMER12_SYSCONFIG    __REG32(OMAP24XX_GPT12 + 0x10)
+
+#define GPIOX_BASE(X)          (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+
+#define GPIO1_SYSCONFIG                __REG32((GPIOX_BASE(1)+0x10))
+#define GPIO2_SYSCONFIG                __REG32((GPIOX_BASE(2)+0x10))
+#define GPIO3_SYSCONFIG                __REG32((GPIOX_BASE(3)+0x10))
+#define GPIO4_SYSCONFIG                __REG32((GPIOX_BASE(4)+0x10))
+
+/* GP TIMER 1 */
+#define GPTIMER1_TISTAT                GPT1_REG32(0x014)
+#define GPTIMER1_TISR          GPT1_REG32(0x018)
+#define GPTIMER1_TIER          GPT1_REG32(0x01C)
+#define GPTIMER1_TWER          GPT1_REG32(0x020)
+#define GPTIMER1_TCLR          GPT1_REG32(0x024)
+#define GPTIMER1_TCRR          GPT1_REG32(0x028)
+#define GPTIMER1_TLDR          GPT1_REG32(0x02C)
+#define GPTIMER1_TTGR          GPT1_REG32(0x030)
+#define GPTIMER1_TWPS          GPT1_REG32(0x034)
+#define GPTIMER1_TMAR          GPT1_REG32(0x038)
+#define GPTIMER1_TCAR1         GPT1_REG32(0x03C)
+#define GPTIMER1_TSICR         GPT1_REG32(0x040)
+#define GPTIMER1_TCAR2         GPT1_REG32(0x044)
+
+/* rkw -- base fix up please... */
+#define GPTIMER3_TISR          __REG32(OMAP24XX_L4_IO_BASE+0x78018)
+
+/* SDRC */
+#define SDRC_DLLA_CTRL         __REG32(OMAP24XX_SDRC_BASE+0x060)
+#define SDRC_DLLA_STATUS       __REG32(OMAP24XX_SDRC_BASE+0x064)
+#define SDRC_DLLB_CTRL         __REG32(OMAP24XX_SDRC_BASE+0x068)
+#define SDRC_DLLB_STATUS       __REG32(OMAP24XX_SDRC_BASE+0x06C)
+#define SDRC_POWER             __REG32(OMAP24XX_SDRC_BASE+0x070)
+#define SDRC_MR_0              __REG32(OMAP24XX_SDRC_BASE+0x084)
+
+/* GPIO 1 */
+#define GPIO1_BASE             GPIOX_BASE(1)
+#define GPIO1_REG32(offset)    __REG32(GPIO1_BASE + (offset))
+#define GPIO1_IRQENABLE1       GPIO1_REG32(0x01C)
+#define GPIO1_IRQSTATUS1       GPIO1_REG32(0x018)
+#define GPIO1_IRQENABLE2       GPIO1_REG32(0x02C)
+#define GPIO1_IRQSTATUS2       GPIO1_REG32(0x028)
+#define GPIO1_WAKEUPENABLE     GPIO1_REG32(0x020)
+#define GPIO1_RISINGDETECT     GPIO1_REG32(0x048)
+#define GPIO1_DATAIN           GPIO1_REG32(0x038)
+#define GPIO1_OE               GPIO1_REG32(0x034)
+#define GPIO1_DATAOUT          GPIO1_REG32(0x03C)
+
+/* GPIO2 */
+#define GPIO2_BASE             GPIOX_BASE(2)
+#define GPIO2_REG32(offset)    __REG32(GPIO2_BASE + (offset))
+#define GPIO2_IRQENABLE1       GPIO2_REG32(0x01C)
+#define GPIO2_IRQSTATUS1       GPIO2_REG32(0x018)
+#define GPIO2_IRQENABLE2       GPIO2_REG32(0x02C)
+#define GPIO2_IRQSTATUS2       GPIO2_REG32(0x028)
+#define GPIO2_WAKEUPENABLE     GPIO2_REG32(0x020)
+#define GPIO2_RISINGDETECT     GPIO2_REG32(0x048)
+#define GPIO2_DATAIN           GPIO2_REG32(0x038)
+#define GPIO2_OE               GPIO2_REG32(0x034)
+#define GPIO2_DATAOUT          GPIO2_REG32(0x03C)
+
+/* GPIO 3 */
+#define GPIO3_BASE             GPIOX_BASE(3)
+#define GPIO3_REG32(offset)    __REG32(GPIO3_BASE + (offset))
+#define GPIO3_IRQENABLE1       GPIO3_REG32(0x01C)
+#define GPIO3_IRQSTATUS1       GPIO3_REG32(0x018)
+#define GPIO3_IRQENABLE2       GPIO3_REG32(0x02C)
+#define GPIO3_IRQSTATUS2       GPIO3_REG32(0x028)
+#define GPIO3_WAKEUPENABLE     GPIO3_REG32(0x020)
+#define GPIO3_RISINGDETECT     GPIO3_REG32(0x048)
+#define GPIO3_FALLINGDETECT    GPIO3_REG32(0x04C)
+#define GPIO3_DATAIN           GPIO3_REG32(0x038)
+#define GPIO3_OE               GPIO3_REG32(0x034)
+#define GPIO3_DATAOUT          GPIO3_REG32(0x03C)
+#define GPIO3_DEBOUNCENABLE    GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME   GPIO3_REG32(0x054)
+
+/* GPIO 4 */
+#define GPIO4_BASE             GPIOX_BASE(4)
+#define GPIO4_REG32(offset)    __REG32(GPIO4_BASE + (offset))
+#define GPIO4_IRQENABLE1       GPIO4_REG32(0x01C)
+#define GPIO4_IRQSTATUS1       GPIO4_REG32(0x018)
+#define GPIO4_IRQENABLE2       GPIO4_REG32(0x02C)
+#define GPIO4_IRQSTATUS2       GPIO4_REG32(0x028)
+#define GPIO4_WAKEUPENABLE     GPIO4_REG32(0x020)
+#define GPIO4_RISINGDETECT     GPIO4_REG32(0x048)
+#define GPIO4_FALLINGDETECT    GPIO4_REG32(0x04C)
+#define GPIO4_DATAIN           GPIO4_REG32(0x038)
+#define GPIO4_OE               GPIO4_REG32(0x034)
+#define GPIO4_DATAOUT          GPIO4_REG32(0x03C)
+#define GPIO4_DEBOUNCENABLE    GPIO4_REG32(0x050)
+#define GPIO4_DEBOUNCINGTIME   GPIO4_REG32(0x054)
+
+
+/* IO CONFIG */
+#define CONTROL_BASE           (OMAP24XX_CTRL_BASE)
+#define CONTROL_REG32(offset)  __REG32(CONTROL_BASE + (offset))
+
+#define CONTROL_PADCONF_SPI1_NCS2      CONTROL_REG32(0x104)
+#define CONTROL_PADCONF_SYS_XTALOUT    CONTROL_REG32(0x134)
+#define CONTROL_PADCONF_UART1_RX       CONTROL_REG32(0x0C8)
+#define CONTROL_PADCONF_MCBSP1_DX      CONTROL_REG32(0x10C)
+#define CONTROL_PADCONF_GPMC_NCS4      CONTROL_REG32(0x090)
+#define CONTROL_PADCONF_DSS_D5         CONTROL_REG32(0x0B8)
+#define CONTROL_PADCONF_DSS_D9         CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D13                CONTROL_REG32(0x0C0)
+#define CONTROL_PADCONF_DSS_VSYNC      CONTROL_REG32(0x0CC)
+
+/* CONTROL */
+#define CONTROL_DEVCONF                CONTROL_REG32(0x274)
+
+/* INTERRUPT CONTROLLER */
+#define INTC_BASE              (OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_REG32(offset)     __REG32(INTC_BASE + (offset))
+
+#define INTC1_U_BASE           INTC_REG32(0x000)
+#define INTC_MIR0              INTC_REG32(0x084)
+#define INTC_MIR_SET0          INTC_REG32(0x08C)
+#define INTC_MIR_CLEAR0                INTC_REG32(0x088)
+#define INTC_ISR_CLEAR0                INTC_REG32(0x094)
+#define INTC_MIR1              INTC_REG32(0x0A4)
+#define INTC_MIR_SET1          INTC_REG32(0x0AC)
+#define INTC_MIR_CLEAR1                INTC_REG32(0x0A8)
+#define INTC_ISR_CLEAR1                INTC_REG32(0x0B4)
+#define INTC_MIR2              INTC_REG32(0x0C4)
+#define INTC_MIR_SET2          INTC_REG32(0x0CC)
+#define INTC_MIR_CLEAR2                INTC_REG32(0x0C8)
+#define INTC_ISR_CLEAR2                INTC_REG32(0x0D4)
+#define INTC_SIR_IRQ           INTC_REG32(0x040)
+#define INTC_CONTROL           INTC_REG32(0x048)
+#define INTC_ILR11             INTC_REG32(0x12C)
+#define INTC_ILR32             INTC_REG32(0x180)
+#define INTC_ILR37             INTC_REG32(0x194)
+#define INTC_SYSCONFIG         INTC_REG32(0x010)
+
+/* RAM FIREWALL */
+#define RAMFW_BASE             (0x68005000)
+#define RAMFW_REG32(offset)    __REG32(RAMFW_BASE + (offset))
+
+#define RAMFW_REQINFOPERM0     RAMFW_REG32(0x048)
+#define RAMFW_READPERM0                RAMFW_REG32(0x050)
+#define RAMFW_WRITEPERM0       RAMFW_REG32(0x058)
+
+/* GPMC CS1 FPGA ON USER INTERFACE MODULE */
+//#define DEBUG_BOARD_LED_REGISTER 0x04000014
+
+/* GPMC CS0 */
+#define GPMC_CONFIG1_0         GPMC_REG32(0x060)
+#define GPMC_CONFIG2_0         GPMC_REG32(0x064)
+#define GPMC_CONFIG3_0         GPMC_REG32(0x068)
+#define GPMC_CONFIG4_0         GPMC_REG32(0x06C)
+#define GPMC_CONFIG5_0         GPMC_REG32(0x070)
+#define GPMC_CONFIG6_0         GPMC_REG32(0x074)
+#define GPMC_CONFIG7_0         GPMC_REG32(0x078)
+
+/* DSS */
+#define DSS_CONTROL            DISP_REG32(0x040)
+#define DISPC_CONTROL          DISP_REG32(0x440)
+#define DISPC_SYSSTATUS                DISP_REG32(0x414)
+#define DISPC_IRQSTATUS                DISP_REG32(0x418)
+#define DISPC_IRQENABLE                DISP_REG32(0x41C)
+#define DISPC_CONFIG           DISP_REG32(0x444)
+#define DISPC_DEFAULT_COLOR0   DISP_REG32(0x44C)
+#define DISPC_DEFAULT_COLOR1   DISP_REG32(0x450)
+#define DISPC_TRANS_COLOR0     DISP_REG32(0x454)
+#define DISPC_TRANS_COLOR1     DISP_REG32(0x458)
+#define DISPC_LINE_NUMBER      DISP_REG32(0x460)
+#define DISPC_TIMING_H         DISP_REG32(0x464)
+#define DISPC_TIMING_V         DISP_REG32(0x468)
+#define DISPC_POL_FREQ         DISP_REG32(0x46C)
+#define DISPC_DIVISOR          DISP_REG32(0x470)
+#define DISPC_SIZE_DIG         DISP_REG32(0x478)
+#define DISPC_SIZE_LCD         DISP_REG32(0x47C)
+#define DISPC_GFX_BA0          DISP_REG32(0x480)
+#define DISPC_GFX_BA1          DISP_REG32(0x484)
+#define DISPC_GFX_POSITION     DISP_REG32(0x488)
+#define DISPC_GFX_SIZE         DISP_REG32(0x48C)
+#define DISPC_GFX_ATTRIBUTES   DISP_REG32(0x4A0)
+#define DISPC_GFX_FIFO_THRESHOLD       DISP_REG32(0x4A4)
+#define DISPC_GFX_ROW_INC      DISP_REG32(0x4AC)
+#define DISPC_GFX_PIXEL_INC    DISP_REG32(0x4B0)
+#define DISPC_GFX_WINDOW_SKIP  DISP_REG32(0x4B4)
+#define DISPC_GFX_TABLE_BA     DISP_REG32(0x4B8)
+#define DISPC_DATA_CYCLE1      DISP_REG32(0x5D4)
+#define DISPC_DATA_CYCLE2      DISP_REG32(0x5D8)
+#define DISPC_DATA_CYCLE3      DISP_REG32(0x5DC)
+
+/* Wake up define for board */
+#define GPIO97                 (1 << 1)
+#define GPIO88                 (1 << 24)
+
+#endif /* __ASSEMBLER__ */
+
+#endif
+
+
+
+
+
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
new file mode 100644 (file)
index 0000000..f4df04f
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * arch/arm/mach-omap/omap2/serial.c
+ *
+ * OMAP2 serial support.
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ *
+ * Based off of arch/arm/mach-omap/omap1/serial.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+#include <asm/arch/common.h>
+#include <asm/arch/board.h>
+
+static struct clk * uart1_ick = NULL;
+static struct clk * uart1_fck = NULL;
+static struct clk * uart2_ick = NULL;
+static struct clk * uart2_fck = NULL;
+static struct clk * uart3_ick = NULL;
+static struct clk * uart3_fck = NULL;
+
+static struct plat_serial8250_port serial_platform_data[] = {
+       {
+               .membase        = (char *)IO_ADDRESS(OMAP_UART1_BASE),
+               .mapbase        = (unsigned long)OMAP_UART1_BASE,
+               .irq            = 72,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = OMAP16XX_BASE_BAUD * 16,
+       }, {
+               .membase        = (char *)IO_ADDRESS(OMAP_UART2_BASE),
+               .mapbase        = (unsigned long)OMAP_UART2_BASE,
+               .irq            = 73,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = OMAP16XX_BASE_BAUD * 16,
+       }, {
+               .membase        = (char *)IO_ADDRESS(OMAP_UART3_BASE),
+               .mapbase        = (unsigned long)OMAP_UART3_BASE,
+               .irq            = 74,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = OMAP16XX_BASE_BAUD * 16,
+       }, {
+               .flags          = 0
+       }
+};
+
+static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
+                                          int offset)
+{
+       offset <<= up->regshift;
+       return (unsigned int)__raw_readb(up->membase + offset);
+}
+
+static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
+                                   int value)
+{
+       offset <<= p->regshift;
+       __raw_writeb(value, (unsigned long)(p->membase + offset));
+}
+
+/*
+ * Internal UARTs need to be initialized for the 8250 autoconfig to work
+ * properly. Note that the TX watermark initialization may not be needed
+ * once the 8250.c watermark handling code is merged.
+ */
+static inline void __init omap_serial_reset(struct plat_serial8250_port *p)
+{
+       serial_write_reg(p, UART_OMAP_MDR1, 0x07);
+       serial_write_reg(p, UART_OMAP_SCR, 0x08);
+       serial_write_reg(p, UART_OMAP_MDR1, 0x00);
+       serial_write_reg(p, UART_OMAP_SYSC, 0x01);
+}
+
+void __init omap_serial_init()
+{
+       int i;
+       const struct omap_uart_config *info;
+
+       /*
+        * Make sure the serial ports are muxed on at this point.
+        * You have to mux them off in device drivers later on
+        * if not needed.
+        */
+
+       info = omap_get_config(OMAP_TAG_UART,
+                              struct omap_uart_config);
+
+       if (info == NULL)
+               return;
+
+       for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+               struct plat_serial8250_port *p = serial_platform_data + i;
+
+               if (!(info->enabled_uarts & (1 << i))) {
+                       p->membase = 0;
+                       p->mapbase = 0;
+                       continue;
+               }
+
+               switch (i) {
+               case 0:
+                       uart1_ick = clk_get(NULL, "uart1_ick");
+                       if (IS_ERR(uart1_ick))
+                               printk("Could not get uart1_ick\n");
+                       else {
+                               clk_use(uart1_ick);
+                       }
+
+                       uart1_fck = clk_get(NULL, "uart1_fck");
+                       if (IS_ERR(uart1_fck))
+                               printk("Could not get uart1_fck\n");
+                       else {
+                               clk_use(uart1_fck);
+                       }
+                       break;
+               case 1:
+                       uart2_ick = clk_get(NULL, "uart2_ick");
+                       if (IS_ERR(uart2_ick))
+                               printk("Could not get uart2_ick\n");
+                       else {
+                               clk_use(uart2_ick);
+                       }
+
+                       uart2_fck = clk_get(NULL, "uart2_fck");
+                       if (IS_ERR(uart2_fck))
+                               printk("Could not get uart2_fck\n");
+                       else {
+                               clk_use(uart2_fck);
+                       }
+                       break;
+               case 2:
+                       uart3_ick = clk_get(NULL, "uart3_ick");
+                       if (IS_ERR(uart3_ick))
+                               printk("Could not get uart3_ick\n");
+                       else {
+                               clk_use(uart3_ick);
+                       }
+
+                       uart3_fck = clk_get(NULL, "uart3_fck");
+                       if (IS_ERR(uart3_fck))
+                               printk("Could not get uart3_fck\n");
+                       else {
+                               clk_use(uart3_fck);
+                       }
+                       break;
+               }
+
+               omap_serial_reset(p);
+       }
+}
+
+static struct platform_device serial_device = {
+       .name                   = "serial8250",
+       .id                     = 0,
+       .dev                    = {
+               .platform_data  = serial_platform_data,
+       },
+};
+
+static int __init omap_init(void)
+{
+       return platform_device_register(&serial_device);
+}
+arch_initcall(omap_init);
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
new file mode 100644 (file)
index 0000000..d59f667
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * linux/arch/arm/mach-omap1/sram.S
+ *
+ * Omap2 specific functions that need to be run in internal SRAM
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/prcm.h>
+
+#define TIMER_32KSYNCT_CR_V    IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
+       
+#define CM_CLKSEL2_PLL_V       IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x544)
+#define PRCM_VOLTCTRL_V                IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x050)  
+#define PRCM_CLKCFG_CTRL_V     IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x080)
+#define CM_CLKEN_PLL_V         IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x500)
+#define CM_IDLEST_CKGEN_V      IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x520)
+#define CM_CLKSEL1_PLL_V       IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x540)
+
+#define SDRC_DLLA_CTRL_V       IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x060)
+#define SDRC_RFR_CTRL_V                IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x0a4)
+
+       .text
+
+ENTRY(sram_ddr_init)
+       stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
+
+       mov     r12, r2                 @ capture CS1 vs CS0
+       mov     r8, r3                  @ capture force parameter
+
+       /* frequency shift down */
+       ldr     r2, cm_clksel2_pll      @ get address of dpllout reg
+       mov     r3, #0x1                @ value for 1x operation
+       str     r3, [r2]                @ go to L1-freq operation
+
+       /* voltage shift down */
+       mov r9, #0x1                    @ set up for L1 voltage call
+       bl voltage_shift                @ go drop voltage
+
+       /* dll lock mode */
+       ldr     r11, sdrc_dlla_ctrl     @ addr of dlla ctrl
+       ldr     r10, [r11]              @ get current val
+       cmp     r12, #0x1               @ cs1 base (2422 es2.05/1)
+       addeq   r11, r11, #0x8          @ if cs1 base, move to DLLB
+       mvn     r9, #0x4                @ mask to get clear bit2
+       and     r10, r10, r9            @ clear bit2 for lock mode.
+       orr     r10, r10, #0x8          @ make sure DLL on (es2 bit pos)
+       orr     r10, r10, #0x2          @ 90 degree phase for all below 133Mhz
+       str     r10, [r11]              @ commit to DLLA_CTRL
+       bl      i_dll_wait              @ wait for dll to lock
+
+       /* get dll value */
+       add     r11, r11, #0x4          @ get addr of status reg
+       ldr     r10, [r11]              @ get locked value
+
+       /* voltage shift up */
+       mov r9, #0x0                    @ shift back to L0-voltage
+       bl voltage_shift                @ go raise voltage
+
+       /* frequency shift up */
+       mov     r3, #0x2                @ value for 2x operation
+       str     r3, [r2]                @ go to L0-freq operation
+
+       /* reset entry mode for dllctrl */
+       sub     r11, r11, #0x4          @ move from status to ctrl
+       cmp     r12, #0x1               @ normalize if cs1 based
+       subeq   r11, r11, #0x8          @ possibly back to DLLA
+       cmp     r8, #0x1                @ if forced unlock exit
+       orreq   r1, r1, #0x4            @ make sure exit with unlocked value
+       str     r1, [r11]               @ restore DLLA_CTRL high value
+       add     r11, r11, #0x8          @ move to DLLB_CTRL addr
+       str     r1, [r11]               @ set value DLLB_CTRL
+       bl      i_dll_wait              @ wait for possible lock
+
+       /* set up for return, DDR should be good */
+       str r10, [r0]                   @ write dll_status and return counter
+       ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
+
+       /* ensure the DLL has relocked */
+i_dll_wait:
+       mov     r4, #0x800              @ delay DLL relock, min 0x400 L3 clocks
+i_dll_delay:
+       subs    r4, r4, #0x1
+       bne     i_dll_delay
+       mov     pc, lr
+
+       /*
+        * shift up or down voltage, use R9 as input to tell level.
+        * wait for it to finish, use 32k sync counter, 1tick=31uS.
+        */
+voltage_shift:
+       ldr     r4, prcm_voltctrl       @ get addr of volt ctrl.
+       ldr     r5, [r4]                @ get value.
+       ldr     r6, prcm_mask_val       @ get value of mask
+       and     r5, r5, r6              @ apply mask to clear bits
+       orr     r5, r5, r9              @ bulld value for L0/L1-volt operation.
+       str     r5, [r4]                @ set up for change.
+       mov     r3, #0x4000             @ get val for force
+       orr     r5, r5, r3              @ build value for force
+       str     r5, [r4]                @ Force transition to L1
+
+       ldr     r3, timer_32ksynct_cr   @ get addr of counter
+       ldr     r5, [r3]                @ get value
+       add     r5, r5, #0x3            @ give it at most 93uS
+volt_delay:
+       ldr     r7, [r3]                @ get timer value
+       cmp     r5, r7                  @ time up?
+       bhi     volt_delay              @ not yet->branch
+       mov     pc, lr                  @ back to caller.
+
+/* relative load constants */
+cm_clksel2_pll:
+       .word CM_CLKSEL2_PLL_V
+sdrc_dlla_ctrl:
+       .word SDRC_DLLA_CTRL_V
+prcm_voltctrl:
+       .word PRCM_VOLTCTRL_V
+prcm_mask_val:
+       .word 0xFFFF3FFC
+timer_32ksynct_cr:
+       .word TIMER_32KSYNCT_CR_V
+ENTRY(sram_ddr_init_sz)
+       .word   . - sram_ddr_init
+
+/*
+ * Reprograms memory timings.
+ * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
+ * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0 
+ */
+ENTRY(sram_reprogram_sdrc)
+       stmfd   sp!, {r0 - r10, lr}     @ save registers on stack
+       mov     r3, #0x0                @ clear for mrc call
+       mcr     p15, 0, r3, c7, c10, 4  @ memory barrier, finish ARM SDR/DDR
+       nop
+       nop
+       ldr     r6, ddr_sdrc_rfr_ctrl   @ get addr of refresh reg
+       ldr     r5, [r6]                @ get value
+       mov     r5, r5, lsr #8          @ isolate rfr field and drop burst
+
+       cmp     r0, #0x1                @ going to half speed?
+       movne   r9, #0x0                @ if up set flag up for pre up, hi volt
+
+       blne    voltage_shift_c         @ adjust voltage
+
+       cmp     r0, #0x1                @ going to half speed (post branch link)
+       moveq   r5, r5, lsr #1          @ divide by 2 if to half
+       movne   r5, r5, lsl #1          @ mult by 2 if to full
+       mov     r5, r5, lsl #8          @ put rfr field back into place
+       add     r5, r5, #0x1            @ turn on burst of 1
+       ldr     r4, ddr_cm_clksel2_pll  @ get address of out reg
+       ldr     r3, [r4]                @ get curr value
+       orr     r3, r3, #0x3
+       bic     r3, r3, #0x3            @ clear lower bits
+       orr     r3, r3, r0              @ new state value
+       str     r3, [r4]                @ set new state (pll/x, x=1 or 2)
+       nop
+       nop
+
+       moveq   r9, #0x1                @ if speed down, post down, drop volt
+       bleq    voltage_shift_c
+
+       mcr     p15, 0, r3, c7, c10, 4  @ memory barrier
+       str     r5, [r6]                @ set new RFR_1 value
+       add     r6, r6, #0x30           @ get RFR_2 addr
+       str     r5, [r6]                @ set RFR_2
+       nop
+       cmp     r2, #0x1                @ (SDR or DDR) do we need to adjust DLL
+       bne     freq_out                @ leave if SDR, no DLL function
+
+       /* With DDR, we need to take care of the DLL for the frequency change */
+       ldr     r2, ddr_sdrc_dlla_ctrl  @ addr of dlla ctrl
+       str     r1, [r2]                @ write out new SDRC_DLLA_CTRL
+       add     r2, r2, #0x8            @ addr to SDRC_DLLB_CTRL
+       str     r1, [r2]                @ commit to SDRC_DLLB_CTRL
+       mov     r1, #0x2000             @ wait DLL relock, min 0x400 L3 clocks 
+dll_wait:
+       subs    r1, r1, #0x1
+       bne     dll_wait
+freq_out:
+       ldmfd   sp!, {r0 - r10, pc}     @ restore regs and return
+
+    /*
+     * shift up or down voltage, use R9 as input to tell level.
+     * wait for it to finish, use 32k sync counter, 1tick=31uS.
+     */
+voltage_shift_c:
+       ldr     r10, ddr_prcm_voltctrl  @ get addr of volt ctrl
+       ldr     r8, [r10]               @ get value
+       ldr     r7, ddr_prcm_mask_val   @ get value of mask
+       and     r8, r8, r7              @ apply mask to clear bits
+       orr     r8, r8, r9              @ bulld value for L0/L1-volt operation.
+       str     r8, [r10]               @ set up for change.
+       mov     r7, #0x4000             @ get val for force
+       orr     r8, r8, r7              @ build value for force
+       str     r8, [r10]               @ Force transition to L1
+
+       ldr     r10, ddr_timer_32ksynct @ get addr of counter
+       ldr     r8, [r10]               @ get value
+       add     r8, r8, #0x2            @ give it at most 62uS (min 31+)
+volt_delay_c:
+       ldr     r7, [r10]               @ get timer value
+       cmp     r8, r7                  @ time up?
+       bhi     volt_delay_c            @ not yet->branch
+       mov     pc, lr                  @ back to caller
+
+ddr_cm_clksel2_pll:
+       .word CM_CLKSEL2_PLL_V
+ddr_sdrc_dlla_ctrl:
+       .word SDRC_DLLA_CTRL_V
+ddr_sdrc_rfr_ctrl:
+       .word SDRC_RFR_CTRL_V
+ddr_prcm_voltctrl:
+       .word PRCM_VOLTCTRL_V
+ddr_prcm_mask_val:
+       .word 0xFFFF3FFC
+ddr_timer_32ksynct:
+       .word TIMER_32KSYNCT_CR_V
+
+ENTRY(sram_reprogram_sdrc_sz)
+       .word   . - sram_reprogram_sdrc
+
+/* 
+ * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
+ */
+ENTRY(sram_set_prcm)
+       stmfd   sp!, {r0-r12, lr}       @ regs to stack
+       adr     r4, pbegin              @ addr of preload start
+       adr     r8, pend                @ addr of preload end
+       mcrr    p15, 1, r8, r4, c12     @ preload into icache
+pbegin:
+       /* move into fast relock bypass */
+       ldr     r8, pll_ctl             @ get addr
+       ldr     r5, [r8]                @ get val
+       mvn     r6, #0x3                @ clear mask
+       and     r5, r5, r6              @ clear field
+       orr     r7, r5, #0x2            @ fast relock val
+       str     r7, [r8]                @ go to fast relock
+       ldr     r4, pll_stat            @ addr of stat
+block:
+       /* wait for bypass */
+       ldr     r8, [r4]                @ stat value
+       and     r8, r8, #0x3            @ mask for stat
+       cmp     r8, #0x1                @ there yet
+       bne     block                   @ loop if not
+
+       /* set new dpll dividers _after_ in bypass */
+       ldr     r4, pll_div             @ get addr
+       str     r0, [r4]                @ set dpll ctrl val
+
+       ldr     r4, set_config          @ get addr
+       mov     r8, #1                  @ valid cfg msk
+       str     r8, [r4]                @ make dividers take
+
+       mov     r4, #100                @ dead spin a bit
+wait_a_bit:
+       subs    r4, r4, #1              @ dec loop
+       bne     wait_a_bit              @ delay done?
+
+       /* check if staying in bypass */
+       cmp     r2, #0x1                @ stay in bypass?
+       beq     pend                    @ jump over dpll relock
+
+       /* relock DPLL with new vals */
+       ldr     r5, pll_stat            @ get addr
+       ldr     r4, pll_ctl             @ get addr
+       orr     r8, r7, #0x3            @ val for lock dpll
+       str     r8, [r4]                @ set val
+       mov     r0, #1000               @ dead spin a bit
+wait_more:
+       subs    r0, r0, #1              @ dec loop
+       bne     wait_more               @ delay done?
+wait_lock:
+       ldr     r8, [r5]                @ get lock val
+       and     r8, r8, #3              @ isolate field
+       cmp     r8, #2                  @ locked?
+       bne     wait_lock               @ wait if not
+pend:
+       /* update memory timings & briefly lock dll */
+       ldr     r4, sdrc_rfr            @ get addr
+       str     r1, [r4]                @ update refresh timing
+       ldr     r11, dlla_ctrl          @ get addr of DLLA ctrl
+       ldr     r10, [r11]              @ get current val
+       mvn     r9, #0x4                @ mask to get clear bit2
+       and     r10, r10, r9            @ clear bit2 for lock mode
+       orr     r10, r10, #0x8          @ make sure DLL on (es2 bit pos)
+       str     r10, [r11]              @ commit to DLLA_CTRL
+       add     r11, r11, #0x8          @ move to dllb
+       str     r10, [r11]              @ hit DLLB also
+
+       mov     r4, #0x800              @ relock time (min 0x400 L3 clocks)
+wait_dll_lock:
+       subs    r4, r4, #0x1
+       bne     wait_dll_lock
+       nop
+       ldmfd   sp!, {r0-r12, pc}       @ restore regs and return
+
+set_config:
+       .word PRCM_CLKCFG_CTRL_V
+pll_ctl:
+       .word CM_CLKEN_PLL_V
+pll_stat:
+       .word CM_IDLEST_CKGEN_V
+pll_div:
+       .word CM_CLKSEL1_PLL_V
+sdrc_rfr:
+       .word SDRC_RFR_CTRL_V
+dlla_ctrl:
+       .word SDRC_DLLA_CTRL_V
+
+ENTRY(sram_set_prcm_sz)
+       .word   . - sram_set_prcm
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
new file mode 100644 (file)
index 0000000..9ec1144
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/arm/mach-omap2/timer-gp.c
+ *
+ * OMAP2 GP timer support.
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt@nokia.com>
+ *         Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * Some parts based off of TI's 24xx code:
+ *
+ *   Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Roughly modelled after the OMAP1 MPU timer code.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <asm/mach/time.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+#define OMAP2_GP_TIMER1_BASE   0x48028000
+#define OMAP2_GP_TIMER2_BASE   0x4802a000
+#define OMAP2_GP_TIMER3_BASE   0x48078000
+#define OMAP2_GP_TIMER4_BASE   0x4807a000
+
+#define GP_TIMER_TIDR          0x00
+#define GP_TIMER_TISR          0x18
+#define GP_TIMER_TIER          0x1c
+#define GP_TIMER_TCLR          0x24
+#define GP_TIMER_TCRR          0x28
+#define GP_TIMER_TLDR          0x2c
+#define GP_TIMER_TSICR         0x40
+
+#define OS_TIMER_NR            1  /* GP timer 2 */
+
+static unsigned long timer_base[] = {
+       IO_ADDRESS(OMAP2_GP_TIMER1_BASE),
+       IO_ADDRESS(OMAP2_GP_TIMER2_BASE),
+       IO_ADDRESS(OMAP2_GP_TIMER3_BASE),
+       IO_ADDRESS(OMAP2_GP_TIMER4_BASE),
+};
+
+static inline unsigned int timer_read_reg(int nr, unsigned int reg)
+{
+       return __raw_readl(timer_base[nr] + reg);
+}
+
+static inline void timer_write_reg(int nr, unsigned int reg, unsigned int val)
+{
+       __raw_writel(val, timer_base[nr] + reg);
+}
+
+/* Note that we always enable the clock prescale divider bit */
+static inline void omap2_gp_timer_start(int nr, unsigned long load_val)
+{
+       unsigned int tmp;
+
+       tmp = 0xffffffff - load_val;
+
+       timer_write_reg(nr, GP_TIMER_TLDR, tmp);
+       timer_write_reg(nr, GP_TIMER_TCRR, tmp);
+       timer_write_reg(nr, GP_TIMER_TIER, 1 << 1);
+       timer_write_reg(nr, GP_TIMER_TCLR, (1 << 5) | (1 << 1) | 1);
+}
+
+static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
+                                           struct pt_regs *regs)
+{
+       write_seqlock(&xtime_lock);
+
+       timer_write_reg(OS_TIMER_NR, GP_TIMER_TISR, 1 << 1);
+       timer_tick(regs);
+
+       write_sequnlock(&xtime_lock);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction omap2_gp_timer_irq = {
+       .name           = "gp timer",
+       .flags          = SA_INTERRUPT,
+       .handler        = omap2_gp_timer_interrupt,
+};
+
+static void __init omap2_gp_timer_init(void)
+{
+       struct clk * sys_ck;
+       u32 tick_period = 120000;
+       u32 l;
+
+       /* Reset clock and prescale value */
+       timer_write_reg(OS_TIMER_NR, GP_TIMER_TCLR, 0);
+
+       sys_ck = clk_get(NULL, "sys_ck");
+       if (IS_ERR(sys_ck))
+               printk(KERN_ERR "Could not get sys_ck\n");
+       else {
+               clk_use(sys_ck);
+               tick_period = clk_get_rate(sys_ck) / 100;
+               clk_put(sys_ck);
+       }
+
+       tick_period /= 2;       /* Minimum prescale divider is 2 */
+       tick_period -= 1;
+
+       l = timer_read_reg(OS_TIMER_NR, GP_TIMER_TIDR);
+       printk(KERN_INFO "OMAP2 GP timer (HW version %d.%d)\n",
+              (l >> 4) & 0x0f, l & 0x0f);
+
+       setup_irq(38, &omap2_gp_timer_irq);
+
+       omap2_gp_timer_start(OS_TIMER_NR, tick_period);
+}
+
+struct sys_timer omap_timer = {
+       .init   = omap2_gp_timer_init,
+};
+
index e3c14d6b4328fdba14c1b58485142d8b20266325..e84fdde6edf8ac680d6ddf5f0821f62f1a6f2ce9 100644 (file)
@@ -102,8 +102,8 @@ config CPU_ARM922T
 # ARM925T
 config CPU_ARM925T
        bool "Support ARM925T processor" if ARCH_OMAP1
-       depends on ARCH_OMAP1510
-       default y if ARCH_OMAP1510
+       depends on ARCH_OMAP15XX
+       default y if ARCH_OMAP15XX
        select CPU_32v4
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
@@ -242,7 +242,7 @@ config CPU_XSCALE
 # ARMv6
 config CPU_V6
        bool "Support ARM V6 processor"
-       depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB
+       depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2
        select CPU_32v6
        select CPU_ABRT_EV6
        select CPU_CACHE_V6
index 59f47d4c2dfe6edf22560b861d6a3d554104dbf1..ffe73ba2bf174d857738d986d1c30240d49bcf50 100644 (file)
@@ -51,4 +51,4 @@ obj-$(CONFIG_CPU_ARM1026)     += proc-arm1026.o
 obj-$(CONFIG_CPU_SA110)                += proc-sa110.o
 obj-$(CONFIG_CPU_SA1100)       += proc-sa1100.o
 obj-$(CONFIG_CPU_XSCALE)       += proc-xscale.o
-obj-$(CONFIG_CPU_V6)           += proc-v6.o blockops.o
+obj-$(CONFIG_CPU_V6)           += proc-v6.o
index 9693e9b4ffd1e70b024803b251b8a3629b5f41f9..c8cbba23f7e893b3d754dd3908429b0189f443a2 100644 (file)
@@ -32,6 +32,32 @@ config OMAP_RESET_CLOCKS
          probably do not want this option enabled until your
          device drivers work properly.
 
+config OMAP_BOOT_TAG
+       bool "OMAP bootloader information passing"
+        depends on ARCH_OMAP
+        default n
+        help
+          Say Y, if you have a bootloader which passes information
+          about your board and its peripheral configuration.
+
+config OMAP_BOOT_REASON
+       bool "Support for boot reason"
+        depends on OMAP_BOOT_TAG
+        default n
+        help
+          Say Y, if you want to have a procfs entry for reading the boot
+          reason in user-space.
+
+config OMAP_GPIO_SWITCH
+       bool "GPIO switch support"
+        depends on OMAP_BOOT_TAG
+        default n
+        help
+          Say Y, if you want to have support for input layer reporting
+          of GPIO switches (e.g. cover switches). Your bootloader has to
+          provide information about the switches to the kernel via the
+          ATAG_BOARD mechanism.
+
 config OMAP_MUX
        bool "OMAP multiplexing support"
         depends on ARCH_OMAP
index 7e144f9cad1c3104c05cce4068fc3d7550ed9c45..bed117dc03dd8f9b3e66509d708c066962efda36 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := common.o sram.o sram-fn.o clock.o dma.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -16,4 +16,8 @@ obj-$(CONFIG_PM) += pm.o sleep.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
+obj-$(CONFIG_OMAP_BOOT_REASON) += bootreason.o
+obj-$(CONFIG_OMAP_GPIO_SWITCH) += gpio-switch.o
 
+# DSP subsystem
+obj-y += dsp/
diff --git a/arch/arm/plat-omap/bootreason.c b/arch/arm/plat-omap/bootreason.c
new file mode 100644 (file)
index 0000000..32d6c9f
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/arm/plat-omap/bootreason.c
+ *
+ * OMAP Bootreason passing
+ *
+ * Copyright (c) 2004 Nokia
+ *
+ * Written by David Weinehall <david.weinehall@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 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/proc_fs.h>
+#include <linux/errno.h>
+#include <asm/arch/board.h>
+
+static char boot_reason[16];
+
+static int omap_bootreason_read_proc(char *page, char **start, off_t off,
+                                    int count, int *eof, void *data)
+{
+       int len = 0;
+
+       len += sprintf(page + len, "%s\n", boot_reason);
+
+       *start = page + off;
+
+       if (len > off)
+               len -= off;
+       else
+               len = 0;
+
+       return len < count ? len  : count;
+}
+
+static int __init bootreason_init(void)
+{
+       const struct omap_boot_reason_config *cfg;
+       int reason_valid = 0;
+       
+       cfg = omap_get_config(OMAP_TAG_BOOT_REASON, struct omap_boot_reason_config);
+       if (cfg != NULL) {
+               strncpy(boot_reason, cfg->reason_str, sizeof(cfg->reason_str));
+               boot_reason[sizeof(cfg->reason_str)] = 0;
+               reason_valid = 1;
+       } else {
+               /* Read the boot reason from the OMAP registers */
+       }
+
+       if (!reason_valid)
+               return -ENOENT;
+
+       printk(KERN_INFO "Bootup reason: %s\n", boot_reason);
+
+       if (!create_proc_read_entry("bootreason", S_IRUGO, NULL,
+                                   omap_bootreason_read_proc, NULL))
+               return -ENOMEM;
+
+       return 0;
+}
+
+late_initcall(bootreason_init);
index a020fe16428fecbd430989927da27ca7d174f53f..7ce39b986e23348622092e3ca8d5627ad0b1af3e 100644 (file)
@@ -1,15 +1,20 @@
 /*
  *  linux/arch/arm/plat-omap/clock.c
  *
- *  Copyright (C) 2004 Nokia corporation
+ *  Copyright (C) 2004 - 2005 Nokia corporation
  *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *
+ *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.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/module.h>
+#include <linux/version.h>
+#include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/hardware/clock.h>
-#include <asm/arch/board.h>
-#include <asm/arch/usb.h>
 
-#include "clock.h"
-#include "sram.h"
+#include <asm/arch/clock.h>
 
-static LIST_HEAD(clocks);
+LIST_HEAD(clocks);
 static DECLARE_MUTEX(clocks_sem);
-static DEFINE_SPINLOCK(clockfw_lock);
-static void propagate_rate(struct clk *  clk);
-/* UART clock function */
-static int set_uart_rate(struct clk * clk, unsigned long rate);
-/* External clock (MCLK & BCLK) functions */
-static int set_ext_clk_rate(struct clk *  clk, unsigned long rate);
-static long round_ext_clk_rate(struct clk *  clk, unsigned long rate);
-static void init_ext_clk(struct clk *  clk);
-/* MPU virtual clock functions */
-static int select_table_rate(struct clk *  clk, unsigned long rate);
-static long round_to_table_rate(struct clk *  clk, unsigned long rate);
-void clk_setdpll(__u16, __u16);
-
-static struct mpu_rate rate_table[] = {
-       /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL
-        * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv
-        */
-#if defined(CONFIG_OMAP_ARM_216MHZ)
-       { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */
-#endif
-#if defined(CONFIG_OMAP_ARM_195MHZ)
-       { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */
-#endif
-#if defined(CONFIG_OMAP_ARM_192MHZ)
-       { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */
-       { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */
-       {  96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */
-       {  48000000, 12000000, 192000000, 0x0baf, 0x2810 }, /* 4/8/4/4/8/8 */
-       {  24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */
-#endif
-#if defined(CONFIG_OMAP_ARM_182MHZ)
-       { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */
-#endif
-#if defined(CONFIG_OMAP_ARM_168MHZ)
-       { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */
-#endif
-#if defined(CONFIG_OMAP_ARM_150MHZ)
-       { 150000000, 12000000, 150000000, 0x010a, 0x2cb0 }, /* 1/1/1/2/4/4 */
-#endif
-#if defined(CONFIG_OMAP_ARM_120MHZ)
-       { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */
-#endif
-#if defined(CONFIG_OMAP_ARM_96MHZ)
-       {  96000000, 12000000,  96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */
-#endif
-#if defined(CONFIG_OMAP_ARM_60MHZ)
-       {  60000000, 12000000,  60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */
-#endif
-#if defined(CONFIG_OMAP_ARM_30MHZ)
-       {  30000000, 12000000,  60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */
-#endif
-       { 0, 0, 0, 0, 0 },
-};
-
-
-static void ckctl_recalc(struct clk *  clk);
-int __clk_enable(struct clk *clk);
-void __clk_disable(struct clk *clk);
-void __clk_unuse(struct clk *clk);
-int __clk_use(struct clk *clk);
-
-
-static void followparent_recalc(struct clk *  clk)
-{
-       clk->rate = clk->parent->rate;
-}
-
-
-static void watchdog_recalc(struct clk *  clk)
-{
-       clk->rate = clk->parent->rate / 14;
-}
-
-static void uart_recalc(struct clk * clk)
-{
-       unsigned int val = omap_readl(clk->enable_reg);
-       if (val & clk->enable_bit)
-               clk->rate = 48000000;
-       else
-               clk->rate = 12000000;
-}
-
-static struct clk ck_ref = {
-       .name           = "ck_ref",
-       .rate           = 12000000,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         ALWAYS_ENABLED,
-};
-
-static struct clk ck_dpll1 = {
-       .name           = "ck_dpll1",
-       .parent         = &ck_ref,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_PROPAGATES | ALWAYS_ENABLED,
-};
-
-static struct clk ck_dpll1out = {
-       .name           = "ck_dpll1out",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_CKOUT_ARM,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk arm_ck = {
-       .name           = "arm_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
-       .rate_offset    = CKCTL_ARMDIV_OFFSET,
-       .recalc         = &ckctl_recalc,
-};
-
-static struct clk armper_ck = {
-       .name           = "armper_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_CKCTL,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_PERCK,
-       .rate_offset    = CKCTL_PERDIV_OFFSET,
-       .recalc         = &ckctl_recalc,
-};
-
-static struct clk arm_gpio_ck = {
-       .name           = "arm_gpio_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_GPIOCK,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk armxor_ck = {
-       .name           = "armxor_ck",
-       .parent         = &ck_ref,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_XORPCK,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk armtim_ck = {
-       .name           = "armtim_ck",
-       .parent         = &ck_ref,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_TIMCK,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk armwdt_ck = {
-       .name           = "armwdt_ck",
-       .parent         = &ck_ref,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_WDTCK,
-       .recalc         = &watchdog_recalc,
-};
-
-static struct clk arminth_ck16xx = {
-       .name           = "arminth_ck",
-       .parent         = &arm_ck,
-       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
-       .recalc         = &followparent_recalc,
-       /* Note: On 16xx the frequency can be divided by 2 by programming
-        * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
-        *
-        * 1510 version is in TC clocks.
-        */
-};
-
-static struct clk dsp_ck = {
-       .name           = "dsp_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_CKCTL,
-       .enable_reg     = ARM_CKCTL,
-       .enable_bit     = EN_DSPCK,
-       .rate_offset    = CKCTL_DSPDIV_OFFSET,
-       .recalc         = &ckctl_recalc,
-};
-
-static struct clk dspmmu_ck = {
-       .name           = "dspmmu_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_CKCTL | ALWAYS_ENABLED,
-       .rate_offset    = CKCTL_DSPMMUDIV_OFFSET,
-       .recalc         = &ckctl_recalc,
-};
-
-static struct clk dspper_ck = {
-       .name           = "dspper_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_CKCTL | DSP_DOMAIN_CLOCK | VIRTUAL_IO_ADDRESS,
-       .enable_reg     = DSP_IDLECT2,
-       .enable_bit     = EN_PERCK,
-       .rate_offset    = CKCTL_PERDIV_OFFSET,
-       .recalc         = &followparent_recalc,
-       //.recalc               = &ckctl_recalc,
-};
-
-static struct clk dspxor_ck = {
-       .name           = "dspxor_ck",
-       .parent         = &ck_ref,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         DSP_DOMAIN_CLOCK | VIRTUAL_IO_ADDRESS,
-       .enable_reg     = DSP_IDLECT2,
-       .enable_bit     = EN_XORPCK,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk dsptim_ck = {
-       .name           = "dsptim_ck",
-       .parent         = &ck_ref,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         DSP_DOMAIN_CLOCK | VIRTUAL_IO_ADDRESS,
-       .enable_reg     = DSP_IDLECT2,
-       .enable_bit     = EN_DSPTIMCK,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk tc_ck = {
-       .name           = "tc_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 |
-                         RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
-       .rate_offset    = CKCTL_TCDIV_OFFSET,
-       .recalc         = &ckctl_recalc,
-};
-
-static struct clk arminth_ck1510 = {
-       .name           = "arminth_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
-       .recalc         = &followparent_recalc,
-       /* Note: On 1510 the frequency follows TC_CK
-        *
-        * 16xx version is in MPU clocks.
-        */
-};
-
-static struct clk tipb_ck = {
-       .name           = "tibp_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk l3_ocpi_ck = {
-       .name           = "l3_ocpi_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT3,
-       .enable_bit     = EN_OCPI_CK,
-       .recalc         = &followparent_recalc,
-};
+DEFINE_SPINLOCK(clockfw_lock);
 
-static struct clk tc1_ck = {
-       .name           = "tc1_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT3,
-       .enable_bit     = EN_TC1_CK,
-       .recalc         = &followparent_recalc,
-};
+static struct clk_functions *arch_clock;
 
-static struct clk tc2_ck = {
-       .name           = "tc2_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT3,
-       .enable_bit     = EN_TC2_CK,
-       .recalc         = &followparent_recalc,
-};
+/*-------------------------------------------------------------------------
+ * Standard clock functions defined in asm/hardware/clock.h
+ *-------------------------------------------------------------------------*/
 
-static struct clk dma_ck = {
-       .name           = "dma_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         ALWAYS_ENABLED,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk dma_lcdfree_ck = {
-       .name           = "dma_lcdfree_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk api_ck = {
-       .name           = "api_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_APICK,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk lb_ck = {
-       .name           = "lb_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP1510,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_LBCK,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk rhea1_ck = {
-       .name           = "rhea1_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk rhea2_ck = {
-       .name           = "rhea2_ck",
-       .parent         = &tc_ck,
-       .flags          = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk lcd_ck = {
-       .name           = "lcd_ck",
-       .parent         = &ck_dpll1,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 |
-                         RATE_CKCTL,
-       .enable_reg     = ARM_IDLECT2,
-       .enable_bit     = EN_LCDCK,
-       .rate_offset    = CKCTL_LCDDIV_OFFSET,
-       .recalc         = &ckctl_recalc,
-};
-
-static struct clk uart1_1510 = {
-       .name           = "uart1_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 12000000,
-       .flags          = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | ALWAYS_ENABLED,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = 29,   /* Chooses between 12MHz and 48MHz */
-       .set_rate       = &set_uart_rate,
-       .recalc         = &uart_recalc,
-};
-
-static struct clk uart1_16xx = {
-       .name           = "uart1_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 48000000,
-       .flags          = CLOCK_IN_OMAP16XX | RATE_FIXED | ENABLE_REG_32BIT,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = 29,
-};
-
-static struct clk uart2_ck = {
-       .name           = "uart2_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 12000000,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ENABLE_REG_32BIT |
-                         ALWAYS_ENABLED,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = 30,   /* Chooses between 12MHz and 48MHz */
-       .set_rate       = &set_uart_rate,
-       .recalc         = &uart_recalc,
-};
-
-static struct clk uart3_1510 = {
-       .name           = "uart3_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 12000000,
-       .flags          = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT | ALWAYS_ENABLED,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = 31,   /* Chooses between 12MHz and 48MHz */
-       .set_rate       = &set_uart_rate,
-       .recalc         = &uart_recalc,
-};
-
-static struct clk uart3_16xx = {
-       .name           = "uart3_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 48000000,
-       .flags          = CLOCK_IN_OMAP16XX | RATE_FIXED | ENABLE_REG_32BIT,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = 31,
-};
-
-static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
-       .name           = "usb_clko",
-       /* Direct from ULPD, no parent */
-       .rate           = 6000000,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_FIXED | ENABLE_REG_32BIT,
-       .enable_reg     = ULPD_CLOCK_CTRL,
-       .enable_bit     = USB_MCLK_EN_BIT,
-};
-
-static struct clk usb_hhc_ck1510 = {
-       .name           = "usb_hhc_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
-       .flags          = CLOCK_IN_OMAP1510 |
-                         RATE_FIXED | ENABLE_REG_32BIT,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = USB_HOST_HHC_UHOST_EN,
-};
-
-static struct clk usb_hhc_ck16xx = {
-       .name           = "usb_hhc_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 48000000,
-       /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
-       .flags          = CLOCK_IN_OMAP16XX |
-                         RATE_FIXED | ENABLE_REG_32BIT,
-       .enable_reg     = OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
-       .enable_bit     = 8 /* UHOST_EN */,
-};
-
-static struct clk usb_dc_ck = {
-       .name           = "usb_dc_ck",
-       /* Direct from ULPD, no parent */
-       .rate           = 48000000,
-       .flags          = CLOCK_IN_OMAP16XX | RATE_FIXED,
-       .enable_reg     = SOFT_REQ_REG,
-       .enable_bit     = 4,
-};
-
-static struct clk mclk_1510 = {
-       .name           = "mclk",
-       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
-       .rate           = 12000000,
-       .flags          = CLOCK_IN_OMAP1510 | RATE_FIXED,
-};
-
-static struct clk mclk_16xx = {
-       .name           = "mclk",
-       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
-       .flags          = CLOCK_IN_OMAP16XX,
-       .enable_reg     = COM_CLK_DIV_CTRL_SEL,
-       .enable_bit     = COM_ULPD_PLL_CLK_REQ,
-       .set_rate       = &set_ext_clk_rate,
-       .round_rate     = &round_ext_clk_rate,
-       .init           = &init_ext_clk,
-};
-
-static struct clk bclk_1510 = {
-       .name           = "bclk",
-       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
-       .rate           = 12000000,
-       .flags          = CLOCK_IN_OMAP1510 | RATE_FIXED,
-};
-
-static struct clk bclk_16xx = {
-       .name           = "bclk",
-       /* Direct from ULPD, no parent. May be enabled by ext hardware. */
-       .flags          = CLOCK_IN_OMAP16XX,
-       .enable_reg     = SWD_CLK_DIV_CTRL_SEL,
-       .enable_bit     = SWD_ULPD_PLL_CLK_REQ,
-       .set_rate       = &set_ext_clk_rate,
-       .round_rate     = &round_ext_clk_rate,
-       .init           = &init_ext_clk,
-};
-
-static struct clk mmc1_ck = {
-       .name           = "mmc1_ck",
-       /* Functional clock is direct from ULPD, interface clock is ARMPER */
-       .parent         = &armper_ck,
-       .rate           = 48000000,
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         RATE_FIXED | ENABLE_REG_32BIT,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = 23,
-};
-
-static struct clk mmc2_ck = {
-       .name           = "mmc2_ck",
-       /* Functional clock is direct from ULPD, interface clock is ARMPER */
-       .parent         = &armper_ck,
-       .rate           = 48000000,
-       .flags          = CLOCK_IN_OMAP16XX |
-                         RATE_FIXED | ENABLE_REG_32BIT,
-       .enable_reg     = MOD_CONF_CTRL_0,
-       .enable_bit     = 20,
-};
-
-static struct clk virtual_ck_mpu = {
-       .name           = "mpu",
-       .flags          = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-                         VIRTUAL_CLOCK | ALWAYS_ENABLED,
-       .parent         = &arm_ck, /* Is smarter alias for */
-       .recalc         = &followparent_recalc,
-       .set_rate       = &select_table_rate,
-       .round_rate     = &round_to_table_rate,
-};
-
-
-static struct clk *  onchip_clks[] = {
-       /* non-ULPD clocks */
-       &ck_ref,
-       &ck_dpll1,
-       /* CK_GEN1 clocks */
-       &ck_dpll1out,
-       &arm_ck,
-       &armper_ck,
-       &arm_gpio_ck,
-       &armxor_ck,
-       &armtim_ck,
-       &armwdt_ck,
-       &arminth_ck1510,  &arminth_ck16xx,
-       /* CK_GEN2 clocks */
-       &dsp_ck,
-       &dspmmu_ck,
-       &dspper_ck,
-       &dspxor_ck,
-       &dsptim_ck,
-       /* CK_GEN3 clocks */
-       &tc_ck,
-       &tipb_ck,
-       &l3_ocpi_ck,
-       &tc1_ck,
-       &tc2_ck,
-       &dma_ck,
-       &dma_lcdfree_ck,
-       &api_ck,
-       &lb_ck,
-       &rhea1_ck,
-       &rhea2_ck,
-       &lcd_ck,
-       /* ULPD clocks */
-       &uart1_1510,
-       &uart1_16xx,
-       &uart2_ck,
-       &uart3_1510,
-       &uart3_16xx,
-       &usb_clko,
-       &usb_hhc_ck1510, &usb_hhc_ck16xx,
-       &usb_dc_ck,
-       &mclk_1510,  &mclk_16xx,
-       &bclk_1510,  &bclk_16xx,
-       &mmc1_ck,
-       &mmc2_ck,
-       /* Virtual clocks */
-       &virtual_ck_mpu,
-};
-
-struct clk *clk_get(struct device *dev, const char *id)
+struct clk * clk_get(struct device *dev, const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
 
@@ -590,534 +53,200 @@ struct clk *clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(clk_get);
 
-
-void clk_put(struct clk *clk)
-{
-       if (clk && !IS_ERR(clk))
-               module_put(clk->owner);
-}
-EXPORT_SYMBOL(clk_put);
-
-
-int __clk_enable(struct clk *clk)
-{
-       __u16 regval16;
-       __u32 regval32;
-
-       if (clk->flags & ALWAYS_ENABLED)
-               return 0;
-
-       if (unlikely(clk->enable_reg == 0)) {
-               printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
-                      clk->name);
-               return 0;
-       }
-
-       if (clk->flags & DSP_DOMAIN_CLOCK) {
-               __clk_use(&api_ck);
-       }
-
-       if (clk->flags & ENABLE_REG_32BIT) {
-               if (clk->flags & VIRTUAL_IO_ADDRESS) {
-                       regval32 = __raw_readl(clk->enable_reg);
-                       regval32 |= (1 << clk->enable_bit);
-                       __raw_writel(regval32, clk->enable_reg);
-               } else {
-                       regval32 = omap_readl(clk->enable_reg);
-                       regval32 |= (1 << clk->enable_bit);
-                       omap_writel(regval32, clk->enable_reg);
-               }
-       } else {
-               if (clk->flags & VIRTUAL_IO_ADDRESS) {
-                       regval16 = __raw_readw(clk->enable_reg);
-                       regval16 |= (1 << clk->enable_bit);
-                       __raw_writew(regval16, clk->enable_reg);
-               } else {
-                       regval16 = omap_readw(clk->enable_reg);
-                       regval16 |= (1 << clk->enable_bit);
-                       omap_writew(regval16, clk->enable_reg);
-               }
-       }
-
-       if (clk->flags & DSP_DOMAIN_CLOCK) {
-               __clk_unuse(&api_ck);
-       }
-
-       return 0;
-}
-
-
-void __clk_disable(struct clk *clk)
-{
-       __u16 regval16;
-       __u32 regval32;
-
-       if (clk->enable_reg == 0)
-               return;
-
-       if (clk->flags & DSP_DOMAIN_CLOCK) {
-               __clk_use(&api_ck);
-       }
-
-       if (clk->flags & ENABLE_REG_32BIT) {
-               if (clk->flags & VIRTUAL_IO_ADDRESS) {
-                       regval32 = __raw_readl(clk->enable_reg);
-                       regval32 &= ~(1 << clk->enable_bit);
-                       __raw_writel(regval32, clk->enable_reg);
-               } else {
-                       regval32 = omap_readl(clk->enable_reg);
-                       regval32 &= ~(1 << clk->enable_bit);
-                       omap_writel(regval32, clk->enable_reg);
-               }
-       } else {
-               if (clk->flags & VIRTUAL_IO_ADDRESS) {
-                       regval16 = __raw_readw(clk->enable_reg);
-                       regval16 &= ~(1 << clk->enable_bit);
-                       __raw_writew(regval16, clk->enable_reg);
-               } else {
-                       regval16 = omap_readw(clk->enable_reg);
-                       regval16 &= ~(1 << clk->enable_bit);
-                       omap_writew(regval16, clk->enable_reg);
-               }
-       }
-
-       if (clk->flags & DSP_DOMAIN_CLOCK) {
-               __clk_unuse(&api_ck);
-       }
-}
-
-
-void __clk_unuse(struct clk *clk)
-{
-       if (clk->usecount > 0 && !(--clk->usecount)) {
-               __clk_disable(clk);
-               if (likely(clk->parent))
-                       __clk_unuse(clk->parent);
-       }
-}
-
-
-int __clk_use(struct clk *clk)
-{
-       int ret = 0;
-       if (clk->usecount++ == 0) {
-               if (likely(clk->parent))
-                       ret = __clk_use(clk->parent);
-
-               if (unlikely(ret != 0)) {
-                       clk->usecount--;
-                       return ret;
-               }
-
-               ret = __clk_enable(clk);
-
-               if (unlikely(ret != 0) && clk->parent) {
-                       __clk_unuse(clk->parent);
-                       clk->usecount--;
-               }
-       }
-
-       return ret;
-}
-
-
 int clk_enable(struct clk *clk)
 {
        unsigned long flags;
-       int ret;
+       int ret = 0;
 
        spin_lock_irqsave(&clockfw_lock, flags);
-       ret = __clk_enable(clk);
+       if (clk->enable)
+               ret = clk->enable(clk);
+       else if (arch_clock->clk_enable)
+               ret = arch_clock->clk_enable(clk);
+       else
+               printk(KERN_ERR "Could not enable clock %s\n", clk->name);
        spin_unlock_irqrestore(&clockfw_lock, flags);
+
        return ret;
 }
 EXPORT_SYMBOL(clk_enable);
 
-
 void clk_disable(struct clk *clk)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&clockfw_lock, flags);
-       __clk_disable(clk);
+       if (clk->disable)
+               clk->disable(clk);
+       else if (arch_clock->clk_disable)
+               arch_clock->clk_disable(clk);
+       else
+               printk(KERN_ERR "Could not disable clock %s\n", clk->name);
        spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
-
 int clk_use(struct clk *clk)
 {
        unsigned long flags;
        int ret = 0;
 
        spin_lock_irqsave(&clockfw_lock, flags);
-       ret = __clk_use(clk);
+       if (arch_clock->clk_use)
+               ret = arch_clock->clk_use(clk);
        spin_unlock_irqrestore(&clockfw_lock, flags);
+
        return ret;
 }
 EXPORT_SYMBOL(clk_use);
 
-
 void clk_unuse(struct clk *clk)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&clockfw_lock, flags);
-       __clk_unuse(clk);
+       if (arch_clock->clk_unuse)
+               arch_clock->clk_unuse(clk);
        spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 EXPORT_SYMBOL(clk_unuse);
 
-
 int clk_get_usecount(struct clk *clk)
 {
-        return clk->usecount;
-}
-EXPORT_SYMBOL(clk_get_usecount);
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-
-static __u16 verify_ckctl_value(__u16 newval)
-{
-       /* This function checks for following limitations set
-        * by the hardware (all conditions must be true):
-        * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
-        * ARM_CK >= TC_CK
-        * DSP_CK >= TC_CK
-        * DSPMMU_CK >= TC_CK
-        *
-        * In addition following rules are enforced:
-        * LCD_CK <= TC_CK
-        * ARMPER_CK <= TC_CK
-        *
-        * However, maximum frequencies are not checked for!
-        */
-       __u8 per_exp;
-       __u8 lcd_exp;
-       __u8 arm_exp;
-       __u8 dsp_exp;
-       __u8 tc_exp;
-       __u8 dspmmu_exp;
-
-       per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
-       lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
-       arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
-       dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
-       tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
-       dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
-
-       if (dspmmu_exp < dsp_exp)
-               dspmmu_exp = dsp_exp;
-       if (dspmmu_exp > dsp_exp+1)
-               dspmmu_exp = dsp_exp+1;
-       if (tc_exp < arm_exp)
-               tc_exp = arm_exp;
-       if (tc_exp < dspmmu_exp)
-               tc_exp = dspmmu_exp;
-       if (tc_exp > lcd_exp)
-               lcd_exp = tc_exp;
-       if (tc_exp > per_exp)
-               per_exp = tc_exp;
+       unsigned long flags;
+       int ret = 0;
 
-       newval &= 0xf000;
-       newval |= per_exp << CKCTL_PERDIV_OFFSET;
-       newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
-       newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
-       newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
-       newval |= tc_exp << CKCTL_TCDIV_OFFSET;
-       newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
+       spin_lock_irqsave(&clockfw_lock, flags);
+       ret = clk->usecount;
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 
-       return newval;
+       return ret;
 }
+EXPORT_SYMBOL(clk_get_usecount);
 
-
-static int calc_dsor_exp(struct clk *clk, unsigned long rate)
+unsigned long clk_get_rate(struct clk *clk)
 {
-       /* Note: If target frequency is too low, this function will return 4,
-        * which is invalid value. Caller must check for this value and act
-        * accordingly.
-        *
-        * Note: This function does not check for following limitations set
-        * by the hardware (all conditions must be true):
-        * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
-        * ARM_CK >= TC_CK
-        * DSP_CK >= TC_CK
-        * DSPMMU_CK >= TC_CK
-        */
-       unsigned long realrate;
-       struct clk *  parent;
-       unsigned  dsor_exp;
-
-       if (unlikely(!(clk->flags & RATE_CKCTL)))
-               return -EINVAL;
-
-       parent = clk->parent;
-       if (unlikely(parent == 0))
-               return -EIO;
-
-       realrate = parent->rate;
-       for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
-               if (realrate <= rate)
-                       break;
+       unsigned long flags;
+       unsigned long ret = 0;
 
-               realrate /= 2;
-       }
+       spin_lock_irqsave(&clockfw_lock, flags);
+       ret = clk->rate;
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 
-       return dsor_exp;
+       return ret;
 }
+EXPORT_SYMBOL(clk_get_rate);
 
-
-static void ckctl_recalc(struct clk *  clk)
+void clk_put(struct clk *clk)
 {
-       int dsor;
-
-       /* Calculate divisor encoded as 2-bit exponent */
-       if (clk->flags & DSP_DOMAIN_CLOCK) {
-               /* The clock control bits are in DSP domain,
-                * so api_ck is needed for access.
-                * Note that DSP_CKCTL virt addr = phys addr, so
-                * we must use __raw_readw() instead of omap_readw().
-                */
-               __clk_use(&api_ck);
-               dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
-               __clk_unuse(&api_ck);
-       } else {
-               dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
-       }
-       if (unlikely(clk->rate == clk->parent->rate / dsor))
-               return; /* No change, quick exit */
-       clk->rate = clk->parent->rate / dsor;
-
-       if (unlikely(clk->flags & RATE_PROPAGATES))
-               propagate_rate(clk);
+       if (clk && !IS_ERR(clk))
+               module_put(clk->owner);
 }
+EXPORT_SYMBOL(clk_put);
 
+/*-------------------------------------------------------------------------
+ * Optional clock functions defined in asm/hardware/clock.h
+ *-------------------------------------------------------------------------*/
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       int dsor_exp;
-
-       if (clk->flags & RATE_FIXED)
-               return clk->rate;
-
-       if (clk->flags & RATE_CKCTL) {
-               dsor_exp = calc_dsor_exp(clk, rate);
-               if (dsor_exp < 0)
-                       return dsor_exp;
-               if (dsor_exp > 3)
-                       dsor_exp = 3;
-               return clk->parent->rate / (1 << dsor_exp);
-       }
+       unsigned long flags;
+       long ret = 0;
 
-       if(clk->round_rate != 0)
-               return clk->round_rate(clk, rate);
+       spin_lock_irqsave(&clockfw_lock, flags);
+       if (arch_clock->clk_round_rate)
+               ret = arch_clock->clk_round_rate(clk, rate);
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 
-       return clk->rate;
+       return ret;
 }
 EXPORT_SYMBOL(clk_round_rate);
 
-
-static void propagate_rate(struct clk *  clk)
-{
-       struct clk **  clkp;
-
-       for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
-               if (likely((*clkp)->parent != clk)) continue;
-               if (likely((*clkp)->recalc))
-                       (*clkp)->recalc(*clkp);
-       }
-}
-
-
-static int select_table_rate(struct clk *  clk, unsigned long rate)
+int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-       /* Find the highest supported frequency <= rate and switch to it */
-       struct mpu_rate *  ptr;
-
-       if (clk != &virtual_ck_mpu)
-               return -EINVAL;
-
-       for (ptr = rate_table; ptr->rate; ptr++) {
-               if (ptr->xtal != ck_ref.rate)
-                       continue;
-
-               /* DPLL1 cannot be reprogrammed without risking system crash */
-               if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate)
-                       continue;
-
-               /* Can check only after xtal frequency check */
-               if (ptr->rate <= rate)
-                       break;
-       }
-
-       if (!ptr->rate)
-               return -EINVAL;
+       unsigned long flags;
+       int ret = 0;
 
-       /*
-        * In most cases we should not need to reprogram DPLL.
-        * Reprogramming the DPLL is tricky, it must be done from SRAM.
-        */
-       omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
+       spin_lock_irqsave(&clockfw_lock, flags);
+       if (arch_clock->clk_set_rate)
+               ret = arch_clock->clk_set_rate(clk, rate);
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 
-       ck_dpll1.rate = ptr->pll_rate;
-       propagate_rate(&ck_dpll1);
-       return 0;
+       return ret;
 }
+EXPORT_SYMBOL(clk_set_rate);
 
-
-static long round_to_table_rate(struct clk *  clk, unsigned long rate)
+int clk_set_parent(struct clk *clk, struct clk *parent)
 {
-       /* Find the highest supported frequency <= rate */
-       struct mpu_rate *  ptr;
-       long  highest_rate;
-
-       if (clk != &virtual_ck_mpu)
-               return -EINVAL;
-
-       highest_rate = -EINVAL;
-
-       for (ptr = rate_table; ptr->rate; ptr++) {
-               if (ptr->xtal != ck_ref.rate)
-                       continue;
-
-               highest_rate = ptr->rate;
+       unsigned long flags;
+       int ret = 0;
 
-               /* Can check only after xtal frequency check */
-               if (ptr->rate <= rate)
-                       break;
-       }
+       spin_lock_irqsave(&clockfw_lock, flags);
+       if (arch_clock->clk_set_parent)
+               ret =  arch_clock->clk_set_parent(clk, parent);
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 
-       return highest_rate;
+       return ret;
 }
+EXPORT_SYMBOL(clk_set_parent);
 
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
+struct clk *clk_get_parent(struct clk *clk)
 {
-       int  ret = -EINVAL;
-       int  dsor_exp;
-       __u16  regval;
-       unsigned long  flags;
-
-       if (clk->flags & RATE_CKCTL) {
-               dsor_exp = calc_dsor_exp(clk, rate);
-               if (dsor_exp > 3)
-                       dsor_exp = -EINVAL;
-               if (dsor_exp < 0)
-                       return dsor_exp;
-
-               spin_lock_irqsave(&clockfw_lock, flags);
-               regval = omap_readw(ARM_CKCTL);
-               regval &= ~(3 << clk->rate_offset);
-               regval |= dsor_exp << clk->rate_offset;
-               regval = verify_ckctl_value(regval);
-               omap_writew(regval, ARM_CKCTL);
-               clk->rate = clk->parent->rate / (1 << dsor_exp);
-               spin_unlock_irqrestore(&clockfw_lock, flags);
-               ret = 0;
-       } else if(clk->set_rate != 0) {
-               spin_lock_irqsave(&clockfw_lock, flags);
-               ret = clk->set_rate(clk, rate);
-               spin_unlock_irqrestore(&clockfw_lock, flags);
-       }
+       unsigned long flags;
+       struct clk * ret = NULL;
 
-       if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
-               propagate_rate(clk);
+       spin_lock_irqsave(&clockfw_lock, flags);
+       if (arch_clock->clk_get_parent)
+               ret = arch_clock->clk_get_parent(clk);
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 
        return ret;
 }
-EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
 
+/*-------------------------------------------------------------------------
+ * OMAP specific clock functions shared between omap1 and omap2
+ *-------------------------------------------------------------------------*/
 
-static unsigned calc_ext_dsor(unsigned long rate)
-{
-       unsigned dsor;
+unsigned int __initdata mpurate;
 
-       /* MCLK and BCLK divisor selection is not linear:
-        * freq = 96MHz / dsor
-        *
-        * RATIO_SEL range: dsor <-> RATIO_SEL
-        * 0..6: (RATIO_SEL+2) <-> (dsor-2)
-        * 6..48:  (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
-        * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
-        * can not be used.
-        */
-       for (dsor = 2; dsor < 96; ++dsor) {
-               if ((dsor & 1) && dsor > 8)
-                       continue;
-               if (rate >= 96000000 / dsor)
-                       break;
-       }
-       return dsor;
-}
-
-/* Only needed on 1510 */
-static int set_uart_rate(struct clk * clk, unsigned long rate)
-{
-       unsigned int val;
-
-       val = omap_readl(clk->enable_reg);
-       if (rate == 12000000)
-               val &= ~(1 << clk->enable_bit);
-       else if (rate == 48000000)
-               val |= (1 << clk->enable_bit);
-       else
-               return -EINVAL;
-       omap_writel(val, clk->enable_reg);
-       clk->rate = rate;
-
-       return 0;
-}
-
-static int set_ext_clk_rate(struct clk *  clk, unsigned long rate)
+/*
+ * By default we use the rate set by the bootloader.
+ * You can override this with mpurate= cmdline option.
+ */
+static int __init omap_clk_setup(char *str)
 {
-       unsigned dsor;
-       __u16 ratio_bits;
+       get_option(&str, &mpurate);
 
-       dsor = calc_ext_dsor(rate);
-       clk->rate = 96000000 / dsor;
-       if (dsor > 8)
-               ratio_bits = ((dsor - 8) / 2 + 6) << 2;
-       else
-               ratio_bits = (dsor - 2) << 2;
+       if (!mpurate)
+               return 1;
 
-       ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd;
-       omap_writew(ratio_bits, clk->enable_reg);
+       if (mpurate < 1000)
+               mpurate *= 1000000;
 
-       return 0;
+       return 1;
 }
+__setup("mpurate=", omap_clk_setup);
 
-
-static long round_ext_clk_rate(struct clk *  clk, unsigned long rate)
+/* Used for clocks that always have same value as the parent clock */
+void followparent_recalc(struct clk *clk)
 {
-       return 96000000 / calc_ext_dsor(rate);
+       clk->rate = clk->parent->rate;
 }
 
-
-static void init_ext_clk(struct clk *  clk)
+/* Propagate rate to children */
+void propagate_rate(struct clk * tclk)
 {
-       unsigned dsor;
-       __u16 ratio_bits;
+       struct clk *clkp;
 
-       /* Determine current rate and ensure clock is based on 96MHz APLL */
-       ratio_bits = omap_readw(clk->enable_reg) & ~1;
-       omap_writew(ratio_bits, clk->enable_reg);
-
-       ratio_bits = (ratio_bits & 0xfc) >> 2;
-       if (ratio_bits > 6)
-               dsor = (ratio_bits - 6) * 2 + 8;
-       else
-               dsor = ratio_bits + 2;
-
-       clk-> rate = 96000000 / dsor;
+       list_for_each_entry(clkp, &clocks, node) {
+               if (likely(clkp->parent != tclk))
+                       continue;
+               if (likely((u32)clkp->recalc))
+                       clkp->recalc(clkp);
+       }
 }
 
-
 int clk_register(struct clk *clk)
 {
        down(&clocks_sem);
@@ -1125,6 +254,7 @@ int clk_register(struct clk *clk)
        if (clk->init)
                clk->init(clk);
        up(&clocks_sem);
+
        return 0;
 }
 EXPORT_SYMBOL(clk_register);
@@ -1137,203 +267,38 @@ void clk_unregister(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_unregister);
 
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-/*
- * Resets some clocks that may be left on from bootloader,
- * but leaves serial clocks on. See also omap_late_clk_reset().
- */
-static inline void omap_early_clk_reset(void)
+void clk_deny_idle(struct clk *clk)
 {
-       //omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
+       unsigned long flags;
+
+       spin_lock_irqsave(&clockfw_lock, flags);
+       if (arch_clock->clk_deny_idle)
+               arch_clock->clk_deny_idle(clk);
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 }
-#else
-#define omap_early_clk_reset() {}
-#endif
+EXPORT_SYMBOL(clk_deny_idle);
 
-int __init clk_init(void)
+void clk_allow_idle(struct clk *clk)
 {
-       struct clk **  clkp;
-       const struct omap_clock_config *info;
-       int crystal_type = 0; /* Default 12 MHz */
-
-       omap_early_clk_reset();
-
-       for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
-               if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) {
-                       clk_register(*clkp);
-                       continue;
-               }
-
-               if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) {
-                       clk_register(*clkp);
-                       continue;
-               }
-
-               if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) {
-                       clk_register(*clkp);
-                       continue;
-               }
-       }
-
-       info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
-       if (info != NULL) {
-               if (!cpu_is_omap1510())
-                       crystal_type = info->system_clock_type;
-       }
-
-#if defined(CONFIG_ARCH_OMAP730)
-       ck_ref.rate = 13000000;
-#elif defined(CONFIG_ARCH_OMAP16XX)
-       if (crystal_type == 2)
-               ck_ref.rate = 19200000;
-#endif
-
-       printk("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n",
-              omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
-              omap_readw(ARM_CKCTL));
-
-       /* We want to be in syncronous scalable mode */
-       omap_writew(0x1000, ARM_SYSST);
-
-#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
-       /* Use values set by bootloader. Determine PLL rate and recalculate
-        * dependent clocks as if kernel had changed PLL or divisors.
-        */
-       {
-               unsigned pll_ctl_val = omap_readw(DPLL_CTL);
-
-               ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */
-               if (pll_ctl_val & 0x10) {
-                       /* PLL enabled, apply multiplier and divisor */
-                       if (pll_ctl_val & 0xf80)
-                               ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7;
-                       ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1;
-               } else {
-                       /* PLL disabled, apply bypass divisor */
-                       switch (pll_ctl_val & 0xc) {
-                       case 0:
-                               break;
-                       case 0x4:
-                               ck_dpll1.rate /= 2;
-                               break;
-                       default:
-                               ck_dpll1.rate /= 4;
-                               break;
-                       }
-               }
-       }
-       propagate_rate(&ck_dpll1);
-#else
-       /* Find the highest supported frequency and enable it */
-       if (select_table_rate(&virtual_ck_mpu, ~0)) {
-               printk(KERN_ERR "System frequencies not set. Check your config.\n");
-               /* Guess sane values (60MHz) */
-               omap_writew(0x2290, DPLL_CTL);
-               omap_writew(0x1005, ARM_CKCTL);
-               ck_dpll1.rate = 60000000;
-               propagate_rate(&ck_dpll1);
-       }
-#endif
-       /* Cache rates for clocks connected to ck_ref (not dpll1) */
-       propagate_rate(&ck_ref);
-       printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
-               "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
-              ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
-              ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
-              arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
-
-#ifdef CONFIG_MACH_OMAP_PERSEUS2
-       /* Select slicer output as OMAP input clock */
-       omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
-#endif
-
-       /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
-       omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
-
-       /* Put DSP/MPUI into reset until needed */
-       omap_writew(0, ARM_RSTCT1);
-       omap_writew(1, ARM_RSTCT2);
-       omap_writew(0x400, ARM_IDLECT1);
-
-       /*
-        * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
-        * of the ARM_IDLECT2 register must be set to zero. The power-on
-        * default value of this bit is one.
-        */
-       omap_writew(0x0000, ARM_IDLECT2);       /* Turn LCD clock off also */
-
-       /*
-        * Only enable those clocks we will need, let the drivers
-        * enable other clocks as necessary
-        */
-       clk_use(&armper_ck);
-       clk_use(&armxor_ck);
-       clk_use(&armtim_ck);
-
-       if (cpu_is_omap1510())
-               clk_enable(&arm_gpio_ck);
+       unsigned long flags;
 
-       return 0;
+       spin_lock_irqsave(&clockfw_lock, flags);
+       if (arch_clock->clk_allow_idle)
+               arch_clock->clk_allow_idle(clk);
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 }
+EXPORT_SYMBOL(clk_allow_idle);
 
+/*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-
-static int __init omap_late_clk_reset(void)
+int __init clk_init(struct clk_functions * custom_clocks)
 {
-       /* Turn off all unused clocks */
-       struct clk *p;
-       __u32 regval32;
-
-       /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
-       regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4);
-       omap_writew(regval32, SOFT_REQ_REG);
-       omap_writew(0, SOFT_REQ_REG2);
-
-       list_for_each_entry(p, &clocks, node) {
-               if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) ||
-                       p->enable_reg == 0)
-                       continue;
-
-               /* Assume no DSP clocks have been activated by bootloader */
-               if (p->flags & DSP_DOMAIN_CLOCK)
-                       continue;
-
-               /* Is the clock already disabled? */
-               if (p->flags & ENABLE_REG_32BIT) {
-                       if (p->flags & VIRTUAL_IO_ADDRESS)
-                               regval32 = __raw_readl(p->enable_reg);
-                       else
-                               regval32 = omap_readl(p->enable_reg);
-               } else {
-                       if (p->flags & VIRTUAL_IO_ADDRESS)
-                               regval32 = __raw_readw(p->enable_reg);
-                       else
-                               regval32 = omap_readw(p->enable_reg);
-               }
-
-               if ((regval32 & (1 << p->enable_bit)) == 0)
-                       continue;
-
-               /* FIXME: This clock seems to be necessary but no-one
-                * has asked for its activation. */
-               if (p == &tc2_ck         // FIX: pm.c (SRAM), CCP, Camera
-                   || p == &ck_dpll1out // FIX: SoSSI, SSR
-                   || p == &arm_gpio_ck // FIX: GPIO code for 1510
-                   ) {
-                       printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
-                              p->name);
-                       continue;
-               }
-
-               printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name);
-               __clk_disable(p);
-               printk(" done\n");
+       if (!custom_clocks) {
+               printk(KERN_ERR "No custom clock functions registered\n");
+               BUG();
        }
 
+       arch_clock = custom_clocks;
+
        return 0;
 }
-
-late_initcall(omap_late_clk_reset);
-
-#endif
diff --git a/arch/arm/plat-omap/clock.h b/arch/arm/plat-omap/clock.h
deleted file mode 100644 (file)
index a89e1e8..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  linux/arch/arm/plat-omap/clock.h
- *
- *  Copyright (C) 2004 Nokia corporation
- *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
- *  Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
- *
- * 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.
- */
-
-#ifndef __ARCH_ARM_OMAP_CLOCK_H
-#define __ARCH_ARM_OMAP_CLOCK_H
-
-struct module;
-
-struct clk {
-       struct list_head        node;
-       struct module           *owner;
-       const char              *name;
-       struct clk              *parent;
-       unsigned long           rate;
-       __s8                    usecount;
-       __u16                   flags;
-       __u32                   enable_reg;
-       __u8                    enable_bit;
-       __u8                    rate_offset;
-       void                    (*recalc)(struct clk *);
-       int                     (*set_rate)(struct clk *, unsigned long);
-       long                    (*round_rate)(struct clk *, unsigned long);
-       void                    (*init)(struct clk *);
-};
-
-
-struct mpu_rate {
-       unsigned long           rate;
-       unsigned long           xtal;
-       unsigned long           pll_rate;
-       __u16                   ckctl_val;
-       __u16                   dpllctl_val;
-};
-
-
-/* Clock flags */
-#define RATE_CKCTL             1
-#define RATE_FIXED             2
-#define RATE_PROPAGATES                4
-#define VIRTUAL_CLOCK          8
-#define ALWAYS_ENABLED         16
-#define ENABLE_REG_32BIT       32
-#define CLOCK_IN_OMAP16XX      64
-#define CLOCK_IN_OMAP1510      128
-#define CLOCK_IN_OMAP730       256
-#define DSP_DOMAIN_CLOCK       512
-#define VIRTUAL_IO_ADDRESS     1024
-
-/* ARM_CKCTL bit shifts */
-#define CKCTL_PERDIV_OFFSET    0
-#define CKCTL_LCDDIV_OFFSET    2
-#define CKCTL_ARMDIV_OFFSET    4
-#define CKCTL_DSPDIV_OFFSET    6
-#define CKCTL_TCDIV_OFFSET     8
-#define CKCTL_DSPMMUDIV_OFFSET 10
-/*#define ARM_TIMXO            12*/
-#define EN_DSPCK               13
-/*#define ARM_INTHCK_SEL       14*/ /* Divide-by-2 for mpu inth_ck */
-/* DSP_CKCTL bit shifts */
-#define CKCTL_DSPPERDIV_OFFSET 0
-
-/* ARM_IDLECT1 bit shifts */
-/*#define IDLWDT_ARM   0*/
-/*#define IDLXORP_ARM  1*/
-/*#define IDLPER_ARM   2*/
-/*#define IDLLCD_ARM   3*/
-/*#define IDLLB_ARM    4*/
-/*#define IDLHSAB_ARM  5*/
-/*#define IDLIF_ARM    6*/
-/*#define IDLDPLL_ARM  7*/
-/*#define IDLAPI_ARM   8*/
-/*#define IDLTIM_ARM   9*/
-/*#define SETARM_IDLE  11*/
-
-/* ARM_IDLECT2 bit shifts */
-#define EN_WDTCK       0
-#define EN_XORPCK      1
-#define EN_PERCK       2
-#define EN_LCDCK       3
-#define EN_LBCK                4 /* Not on 1610/1710 */
-/*#define EN_HSABCK    5*/
-#define EN_APICK       6
-#define EN_TIMCK       7
-#define DMACK_REQ      8
-#define EN_GPIOCK      9 /* Not on 1610/1710 */
-/*#define EN_LBFREECK  10*/
-#define EN_CKOUT_ARM   11
-
-/* ARM_IDLECT3 bit shifts */
-#define EN_OCPI_CK     0
-#define EN_TC1_CK      2
-#define EN_TC2_CK      4
-
-/* DSP_IDLECT2 bit shifts (0,1,2 are same as for ARM_IDLECT2) */
-#define EN_DSPTIMCK    5
-
-/* Various register defines for clock controls scattered around OMAP chip */
-#define USB_MCLK_EN_BIT                4       /* In ULPD_CLKC_CTRL */
-#define USB_HOST_HHC_UHOST_EN  9       /* In MOD_CONF_CTRL_0 */
-#define SWD_ULPD_PLL_CLK_REQ   1       /* In SWD_CLK_DIV_CTRL_SEL */
-#define COM_ULPD_PLL_CLK_REQ   1       /* In COM_CLK_DIV_CTRL_SEL */
-#define SWD_CLK_DIV_CTRL_SEL   0xfffe0874
-#define COM_CLK_DIV_CTRL_SEL   0xfffe0878
-#define SOFT_REQ_REG           0xfffe0834
-#define SOFT_REQ_REG2          0xfffe0880
-
-int clk_register(struct clk *clk);
-void clk_unregister(struct clk *clk);
-int clk_init(void);
-
-#endif
index 02bcc6c1cd1b136284d4a76d1fb067e714544f4a..7c60ed11ba3e1d0beae9f62dc25f5a19075bd2db 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/fpga.h>
 
-#include "clock.h"
+#include <asm/arch/clock.h>
 
 #define NO_LENGTH_CHECK 0xffffffff
 
@@ -41,6 +41,26 @@ int omap_bootloader_tag_len;
 struct omap_board_config_kernel *omap_board_config;
 int omap_board_config_size;
 
+#ifdef CONFIG_OMAP_BOOT_TAG
+
+static int __init parse_tag_omap(const struct tag *tag)
+{
+       u32 size = tag->hdr.size - (sizeof(tag->hdr) >> 2);
+
+        size <<= 2;
+       if (size > sizeof(omap_bootloader_tag))
+               return -1;
+
+       memcpy(omap_bootloader_tag, tag->u.omap.data, size);
+       omap_bootloader_tag_len = size;
+
+        return 0;
+}
+
+__tagtable(ATAG_BOARD, parse_tag_omap);
+
+#endif
+
 static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
 {
        struct omap_board_config_kernel *kinfo = NULL;
@@ -117,19 +137,43 @@ 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;
+       const struct omap_serial_console_config *con_info;
+       const struct omap_uart_config *uart_info;
+       static char speed[11], *opt = NULL;
+       int line, i, uart_idx;
+
+       uart_info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
+       con_info = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
+                                       struct omap_serial_console_config);
+       if (uart_info == NULL || con_info == NULL)
+               return 0;
+
+       if (con_info->console_uart == 0)
+               return 0;
+
+       if (con_info->console_speed) {
+               snprintf(speed, sizeof(speed), "%u", con_info->console_speed);
+               opt = speed;
+       }
 
-               if (info->console_speed) {
-                       snprintf(speed, sizeof(speed), "%u", info->console_speed);
-                       opt = speed;
-               }
-               return add_preferred_console("ttyS", info->console_uart - 1, opt);
+       uart_idx = con_info->console_uart - 1;
+       if (uart_idx >= OMAP_MAX_NR_PORTS) {
+               printk(KERN_INFO "Console: external UART#%d. "
+                       "Not adding it as console this time.\n",
+                       uart_idx + 1);
+               return 0;
+       }
+       if (!(uart_info->enabled_uarts & (1 << uart_idx))) {
+               printk(KERN_ERR "Console: Selected UART#%d is "
+                       "not enabled for this platform\n",
+                       uart_idx + 1);
+               return -1;
+       }
+       line = 0;
+       for (i = 0; i < uart_idx; i++) {
+               if (uart_info->enabled_uarts & (1 << i))
+                       line++;
        }
-       return 0;
+       return add_preferred_console("ttyS", line, opt);
 }
 console_initcall(omap_add_serial_console);
diff --git a/arch/arm/plat-omap/common.h b/arch/arm/plat-omap/common.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
new file mode 100644 (file)
index 0000000..9dcce90
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * linux/arch/arm/plat-omap/devices.c
+ *
+ * Common platform device setup/initialization for OMAP1 and OMAP2
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/tc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
+
+
+void omap_nop_release(struct device *dev)
+{
+        /* Nothing */
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+
+#define        OMAP1_I2C_BASE          0xfffb3800
+#define OMAP2_I2C_BASE1                0x48070000
+#define OMAP_I2C_SIZE          0x3f
+#define OMAP1_I2C_INT          INT_I2C
+#define OMAP2_I2C_INT1         56
+
+static struct resource i2c_resources1[] = {
+       {
+               .start          = 0,
+               .end            = 0,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = 0,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+/* DMA not used; works around erratum writing to non-empty i2c fifo */
+
+static struct platform_device omap_i2c_device1 = {
+        .name           = "i2c_omap",
+        .id             = 1,
+        .dev = {
+                .release        = omap_nop_release,
+        },
+       .num_resources  = ARRAY_SIZE(i2c_resources1),
+       .resource       = i2c_resources1,
+};
+
+/* See also arch/arm/mach-omap2/devices.c for second I2C on 24xx */
+static void omap_init_i2c(void)
+{
+       if (cpu_is_omap24xx()) {
+               i2c_resources1[0].start = OMAP2_I2C_BASE1;
+               i2c_resources1[0].end = OMAP2_I2C_BASE1 + OMAP_I2C_SIZE;
+               i2c_resources1[1].start = OMAP2_I2C_INT1;
+       } else {
+               i2c_resources1[0].start = OMAP1_I2C_BASE;
+               i2c_resources1[0].end = OMAP1_I2C_BASE + OMAP_I2C_SIZE;
+               i2c_resources1[1].start = OMAP1_I2C_INT;
+       }
+
+       /* FIXME define and use a boot tag, in case of boards that
+        * either don't wire up I2C, or chips that mux it differently...
+        * it can include clocking and address info, maybe more.
+        */
+       if (cpu_is_omap24xx()) {
+               omap_cfg_reg(M19_24XX_I2C1_SCL);
+               omap_cfg_reg(L15_24XX_I2C1_SDA);
+       } else {
+               omap_cfg_reg(I2C_SCL);
+               omap_cfg_reg(I2C_SDA);
+       }
+
+       (void) platform_device_register(&omap_i2c_device1);
+}
+
+#else
+static inline void omap_init_i2c(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#if    defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define        OMAP_MMC1_BASE          0x4809c000
+#define OMAP_MMC1_INT          83
+#else
+#define        OMAP_MMC1_BASE          0xfffb7800
+#define OMAP_MMC1_INT          INT_MMC
+#endif
+#define        OMAP_MMC2_BASE          0xfffb7c00      /* omap16xx only */
+
+static struct omap_mmc_conf mmc1_conf;
+
+static u64 mmc1_dmamask = 0xffffffff;
+
+static struct resource mmc1_resources[] = {
+       {
+               .start          = IO_ADDRESS(OMAP_MMC1_BASE),
+               .end            = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = OMAP_MMC1_INT,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device mmc_omap_device1 = {
+       .name           = "mmci-omap",
+       .id             = 1,
+       .dev = {
+               .release        = omap_nop_release,
+               .dma_mask       = &mmc1_dmamask,
+               .platform_data  = &mmc1_conf,
+       },
+       .num_resources  = ARRAY_SIZE(mmc1_resources),
+       .resource       = mmc1_resources,
+};
+
+#ifdef CONFIG_ARCH_OMAP16XX
+
+static struct omap_mmc_conf mmc2_conf;
+
+static u64 mmc2_dmamask = 0xffffffff;
+
+static struct resource mmc2_resources[] = {
+       {
+               .start          = IO_ADDRESS(OMAP_MMC2_BASE),
+               .end            = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = INT_1610_MMC2,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device mmc_omap_device2 = {
+       .name           = "mmci-omap",
+       .id             = 2,
+       .dev = {
+               .release        = omap_nop_release,
+               .dma_mask       = &mmc2_dmamask,
+               .platform_data  = &mmc2_conf,
+       },
+       .num_resources  = ARRAY_SIZE(mmc2_resources),
+       .resource       = mmc2_resources,
+};
+#endif
+
+static void __init omap_init_mmc(void)
+{
+       const struct omap_mmc_config    *mmc_conf;
+       const struct omap_mmc_conf      *mmc;
+
+       /* NOTE:  assumes MMC was never (wrongly) enabled */
+       mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config);
+       if (!mmc_conf)
+               return;
+
+       /* block 1 is always available and has just one pinout option */
+       mmc = &mmc_conf->mmc[0];
+       if (mmc->enabled) {
+               if (!cpu_is_omap24xx()) {
+                       omap_cfg_reg(MMC_CMD);
+                       omap_cfg_reg(MMC_CLK);
+                       omap_cfg_reg(MMC_DAT0);
+                       if (cpu_is_omap1710()) {
+                               omap_cfg_reg(M15_1710_MMC_CLKI);
+                               omap_cfg_reg(P19_1710_MMC_CMDDIR);
+                               omap_cfg_reg(P20_1710_MMC_DATDIR0);
+                       }
+               }
+               if (mmc->wire4) {
+                       if (!cpu_is_omap24xx()) {
+                               omap_cfg_reg(MMC_DAT1);
+                               /* NOTE:  DAT2 can be on W10 (here) or M15 */
+                               if (!mmc->nomux)
+                                       omap_cfg_reg(MMC_DAT2);
+                               omap_cfg_reg(MMC_DAT3);
+                       }
+               }
+               mmc1_conf = *mmc;
+               (void) platform_device_register(&mmc_omap_device1);
+       }
+
+#ifdef CONFIG_ARCH_OMAP16XX
+       /* block 2 is on newer chips, and has many pinout options */
+       mmc = &mmc_conf->mmc[1];
+       if (mmc->enabled) {
+               if (!mmc->nomux) {
+                       omap_cfg_reg(Y8_1610_MMC2_CMD);
+                       omap_cfg_reg(Y10_1610_MMC2_CLK);
+                       omap_cfg_reg(R18_1610_MMC2_CLKIN);
+                       omap_cfg_reg(W8_1610_MMC2_DAT0);
+                       if (mmc->wire4) {
+                               omap_cfg_reg(V8_1610_MMC2_DAT1);
+                               omap_cfg_reg(W15_1610_MMC2_DAT2);
+                               omap_cfg_reg(R10_1610_MMC2_DAT3);
+                       }
+
+                       /* These are needed for the level shifter */
+                       omap_cfg_reg(V9_1610_MMC2_CMDDIR);
+                       omap_cfg_reg(V5_1610_MMC2_DATDIR0);
+                       omap_cfg_reg(W19_1610_MMC2_DATDIR1);
+               }
+
+               /* Feedback clock must be set on OMAP-1710 MMC2 */
+               if (cpu_is_omap1710())
+                       omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
+                                    MOD_CONF_CTRL_1);
+               mmc2_conf = *mmc;
+               (void) platform_device_register(&mmc_omap_device2);
+       }
+#endif
+       return;
+}
+#else
+static inline void omap_init_mmc(void) {}
+#endif
+
+#if    defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define        OMAP_WDT_BASE           0x48022000
+#else
+#define        OMAP_WDT_BASE           0xfffeb000
+#endif
+
+static struct resource wdt_resources[] = {
+       {
+               .start          = OMAP_WDT_BASE,
+               .end            = OMAP_WDT_BASE + 0x4f,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap_wdt_device = {
+       .name      = "omap_wdt",
+       .id          = -1,
+       .dev = {
+               .release        = omap_nop_release,
+       },
+       .num_resources  = ARRAY_SIZE(wdt_resources),
+       .resource       = wdt_resources,
+};
+
+static void omap_init_wdt(void)
+{
+       (void) platform_device_register(&omap_wdt_device);
+}
+#else
+static inline void omap_init_wdt(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#if    defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE)
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define        OMAP_RNG_BASE           0x480A0000
+#else
+#define        OMAP_RNG_BASE           0xfffe5000
+#endif
+
+static struct resource rng_resources[] = {
+       {
+               .start          = OMAP_RNG_BASE,
+               .end            = OMAP_RNG_BASE + 0x4f,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap_rng_device = {
+       .name      = "omap_rng",
+       .id          = -1,
+       .dev = {
+               .release        = omap_nop_release,
+       },
+       .num_resources  = ARRAY_SIZE(rng_resources),
+       .resource       = rng_resources,
+};
+
+static void omap_init_rng(void)
+{
+       (void) platform_device_register(&omap_rng_device);
+}
+#else
+static inline void omap_init_rng(void) {}
+#endif
+
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+static struct omap_lcd_config omap_fb_conf;
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+       .name           = "omapfb",
+       .id             = -1,
+       .dev = {
+               .release                = omap_nop_release,
+               .dma_mask               = &omap_fb_dma_mask,
+               .coherent_dma_mask      = ~(u32)0,
+               .platform_data          = &omap_fb_conf,
+       },
+       .num_resources = 0,
+};
+
+static inline void omap_init_fb(void)
+{
+       const struct omap_lcd_config *conf;
+
+       conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+       if (conf != NULL)
+               omap_fb_conf = *conf;
+       platform_device_register(&omap_fb_device);
+}
+
+#else
+
+static inline void omap_init_fb(void) {}
+
+#endif
+
+/*
+ * This gets called after board-specific INIT_MACHINE, and initializes most
+ * on-chip peripherals accessible on this board (except for few like USB):
+ *
+ *  (a) Does any "standard config" pin muxing needed.  Board-specific
+ *     code will have muxed GPIO pins and done "nonstandard" setup;
+ *     that code could live in the boot loader.
+ *  (b) Populating board-specific platform_data with the data drivers
+ *     rely on to handle wiring variations.
+ *  (c) Creating platform devices as meaningful on this board and
+ *     with this kernel configuration.
+ *
+ * Claiming GPIOs, and setting their direction and initial values, is the
+ * responsibility of the device drivers.  So is responding to probe().
+ *
+ * Board-specific knowlege like creating devices or pin setup is to be
+ * kept out of drivers as much as possible.  In particular, pin setup
+ * may be handled by the boot loader, and drivers should expect it will
+ * normally have been done by the time they're probed.
+ */
+static int __init omap_init_devices(void)
+{
+       /* please keep these calls, and their implementations above,
+        * in alphabetical order so they're easier to sort through.
+        */
+       omap_init_fb();
+       omap_init_i2c();
+       omap_init_mmc();
+       omap_init_wdt();
+       omap_init_rng();
+
+       return 0;
+}
+arch_initcall(omap_init_devices);
+
index da7b6514565884e894d82f729ee38274d63ae46d..907c0122a694189ad080af49f8992df6a8d98b70 100644 (file)
@@ -6,6 +6,8 @@
  * 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>
+ * OMAP2 support Copyright (C) 2004-2005 Texas Instruments, Inc.
+ * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
  * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
  *
  * Support functions for the OMAP internal DMA channels.
 
 #include <asm/arch/tc.h>
 
-#define OMAP_DMA_ACTIVE                0x01
+#define DEBUG_PRINTS
+#undef DEBUG_PRINTS
+#ifdef DEBUG_PRINTS
+#define debug_printk(x) printk x
+#else
+#define        debug_printk(x)
+#endif
 
+#define OMAP_DMA_ACTIVE                0x01
 #define OMAP_DMA_CCR_EN                (1 << 7)
 
 #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
@@ -55,7 +64,7 @@ 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] = {
+const static u8 omap1_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,
@@ -63,6 +72,20 @@ const static u8 dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
        INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
 };
 
+#define REVISIT_24XX()         printk(KERN_ERR "FIXME: no %s on 24xx\n", \
+                                               __FUNCTION__);
+
+#ifdef CONFIG_ARCH_OMAP15XX
+/* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
+int omap_dma_in_1510_mode(void)
+{
+       return enable_1510_mode;
+}
+#else
+#define omap_dma_in_1510_mode()                0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1
 static inline int get_gdma_dev(int req)
 {
        u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4;
@@ -82,6 +105,9 @@ static inline void set_gdma_dev(int req, int dev)
        l |= (dev - 1) << shift;
        omap_writel(l, reg);
 }
+#else
+#define set_gdma_dev(req, dev) do {} while (0)
+#endif
 
 static void clear_lch_regs(int lch)
 {
@@ -121,38 +147,62 @@ void omap_set_dma_priority(int dst_port, int priority)
 }
 
 void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
-                                 int frame_count, int sync_mode)
+                                 int frame_count, int sync_mode,
+                                 int dma_trigger, int src_or_dst_synch)
 {
-       u16 w;
+       OMAP_DMA_CSDP_REG(lch) &= ~0x03;
+       OMAP_DMA_CSDP_REG(lch) |= data_type;
 
-       w = omap_readw(OMAP_DMA_CSDP(lch));
-       w &= ~0x03;
-       w |= data_type;
-       omap_writew(w, OMAP_DMA_CSDP(lch));
+       if (cpu_class_is_omap1()) {     
+               OMAP_DMA_CCR_REG(lch) &= ~(1 << 5);
+               if (sync_mode == OMAP_DMA_SYNC_FRAME)
+                       OMAP_DMA_CCR_REG(lch) |= 1 << 5;
+
+               OMAP1_DMA_CCR2_REG(lch) &= ~(1 << 2);
+               if (sync_mode == OMAP_DMA_SYNC_BLOCK)
+                       OMAP1_DMA_CCR2_REG(lch) |= 1 << 2;
+       }
+
+       if (cpu_is_omap24xx() && dma_trigger) {
+               u32 val = OMAP_DMA_CCR_REG(lch);
+
+               if (dma_trigger > 63)
+                       val |= 1 << 20;
+               if (dma_trigger > 31)
+                       val |= 1 << 19;
 
-       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));
+               val |= (dma_trigger & 0x1f);
 
-       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));
+               if (sync_mode & OMAP_DMA_SYNC_FRAME)
+                       val |= 1 << 5;
 
-       omap_writew(elem_count, OMAP_DMA_CEN(lch));
-       omap_writew(frame_count, OMAP_DMA_CFN(lch));
+               if (sync_mode & OMAP_DMA_SYNC_BLOCK)
+                       val |= 1 << 18;
 
+               if (src_or_dst_synch)
+                       val |= 1 << 24;         /* source synch */
+               else
+                       val &= ~(1 << 24);      /* dest synch */
+
+               OMAP_DMA_CCR_REG(lch) = val;
+       }
+
+       OMAP_DMA_CEN_REG(lch) = elem_count;
+       OMAP_DMA_CFN_REG(lch) = frame_count;
 }
+
 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;
+       if (cpu_is_omap24xx()) {
+               REVISIT_24XX();
+               return;
+       }
+
+       w = OMAP1_DMA_CCR2_REG(lch) & ~0x03;
        switch (mode) {
        case OMAP_DMA_CONSTANT_FILL:
                w |= 0x01;
@@ -165,63 +215,84 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
        default:
                BUG();
        }
-       omap_writew(w, OMAP_DMA_CCR2(lch));
+       OMAP1_DMA_CCR2_REG(lch) = w;
 
-       w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f;
+       w = OMAP1_DMA_LCH_CTRL_REG(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));
+               OMAP1_DMA_COLOR_L_REG(lch) = (u16)color;
+               OMAP1_DMA_COLOR_U_REG(lch) = (u16)(color >> 16);
                w |= 1;         /* Channel type G */
        }
-       omap_writew(w, OMAP_DMA_LCH_CTRL(lch));
+       OMAP1_DMA_LCH_CTRL_REG(lch) = w;
 }
 
-
+/* Note that src_port is only for omap1 */
 void omap_set_dma_src_params(int lch, int src_port, int src_amode,
-                            unsigned long src_start)
+                            unsigned long src_start,
+                            int src_ei, int src_fi)
 {
-       u16 w;
+       if (cpu_class_is_omap1()) {
+               OMAP_DMA_CSDP_REG(lch) &= ~(0x1f << 2);
+               OMAP_DMA_CSDP_REG(lch) |= src_port << 2;
+       }
 
-       w = omap_readw(OMAP_DMA_CSDP(lch));
-       w &= ~(0x1f << 2);
-       w |= src_port << 2;
-       omap_writew(w, OMAP_DMA_CSDP(lch));
+       OMAP_DMA_CCR_REG(lch) &= ~(0x03 << 12);
+       OMAP_DMA_CCR_REG(lch) |= src_amode << 12;
 
-       w = omap_readw(OMAP_DMA_CCR(lch));
-       w &= ~(0x03 << 12);
-       w |= src_amode << 12;
-       omap_writew(w, OMAP_DMA_CCR(lch));
+       if (cpu_class_is_omap1()) {
+               OMAP1_DMA_CSSA_U_REG(lch) = src_start >> 16;
+               OMAP1_DMA_CSSA_L_REG(lch) = src_start;
+       }
+
+       if (cpu_is_omap24xx())
+               OMAP2_DMA_CSSA_REG(lch) = src_start;
+               
+       OMAP_DMA_CSEI_REG(lch) = src_ei;
+       OMAP_DMA_CSFI_REG(lch) = src_fi;
+}
 
-       omap_writew(src_start >> 16, OMAP_DMA_CSSA_U(lch));
-       omap_writew(src_start, OMAP_DMA_CSSA_L(lch));
+void omap_set_dma_params(int lch, struct omap_dma_channel_params * params)
+{
+       omap_set_dma_transfer_params(lch, params->data_type,
+                                    params->elem_count, params->frame_count,
+                                    params->sync_mode, params->trigger,
+                                    params->src_or_dst_synch);
+       omap_set_dma_src_params(lch, params->src_port,
+                               params->src_amode, params->src_start,
+                               params->src_ei, params->src_fi);
+
+       omap_set_dma_dest_params(lch, params->dst_port,
+                                params->dst_amode, params->dst_start,
+                                params->dst_ei, params->dst_fi);
 }
 
 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));
+       if (cpu_is_omap24xx()) {
+               REVISIT_24XX();
+               return;
+       }
+       OMAP_DMA_CSEI_REG(lch) = eidx;
+       OMAP_DMA_CSFI_REG(lch) = fidx;
 }
 
 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));
+       OMAP_DMA_CSDP_REG(lch) &= ~(1 << 6);
+       if (enable)
+               OMAP_DMA_CSDP_REG(lch) |= (1 << 6);
 }
 
 void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 {
-       u16 w;
+       OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 7);
 
-       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);
+               OMAP_DMA_CSDP_REG(lch) |= (0x02 << 7);
                break;
        case OMAP_DMA_DATA_BURST_8:
                /* not supported by current hardware
@@ -231,110 +302,283 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
        default:
                BUG();
        }
-       omap_writew(w, OMAP_DMA_CSDP(lch));
 }
 
+/* Note that dest_port is only for OMAP1 */
 void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
-                             unsigned long dest_start)
+                             unsigned long dest_start,
+                             int dst_ei, int dst_fi)
 {
-       u16 w;
+       if (cpu_class_is_omap1()) {
+               OMAP_DMA_CSDP_REG(lch) &= ~(0x1f << 9);
+               OMAP_DMA_CSDP_REG(lch) |= dest_port << 9;
+       }
+
+       OMAP_DMA_CCR_REG(lch) &= ~(0x03 << 14);
+       OMAP_DMA_CCR_REG(lch) |= dest_amode << 14;
 
-       w = omap_readw(OMAP_DMA_CSDP(lch));
-       w &= ~(0x1f << 9);
-       w |= dest_port << 9;
-       omap_writew(w, OMAP_DMA_CSDP(lch));
+       if (cpu_class_is_omap1()) {
+               OMAP1_DMA_CDSA_U_REG(lch) = dest_start >> 16;
+               OMAP1_DMA_CDSA_L_REG(lch) = dest_start;
+       }
 
-       w = omap_readw(OMAP_DMA_CCR(lch));
-       w &= ~(0x03 << 14);
-       w |= dest_amode << 14;
-       omap_writew(w, OMAP_DMA_CCR(lch));
+       if (cpu_is_omap24xx())
+               OMAP2_DMA_CDSA_REG(lch) = dest_start;   
 
-       omap_writew(dest_start >> 16, OMAP_DMA_CDSA_U(lch));
-       omap_writew(dest_start, OMAP_DMA_CDSA_L(lch));
+       OMAP_DMA_CDEI_REG(lch) = dst_ei;
+       OMAP_DMA_CDFI_REG(lch) = dst_fi;
 }
 
 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));
+       if (cpu_is_omap24xx()) {
+               REVISIT_24XX();
+               return;
+       }
+       OMAP_DMA_CDEI_REG(lch) = eidx;
+       OMAP_DMA_CDFI_REG(lch) = fidx;
 }
 
 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));
+       OMAP_DMA_CSDP_REG(lch) &= ~(1 << 13);
+       if (enable)
+               OMAP_DMA_CSDP_REG(lch) |= 1 << 13;
 }
 
 void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 {
-       u16 w;
+       OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 14);
 
-       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);
+               OMAP_DMA_CSDP_REG(lch) |= (0x02 << 14);
                break;
        case OMAP_DMA_DATA_BURST_8:
-               w |= (0x03 << 14);
+               OMAP_DMA_CSDP_REG(lch) |= (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)
+static inline void omap_enable_channel_irq(int lch)
 {
-       u16 w;
+       u32 status;
 
        /* Read CSR to make sure it's cleared. */
-       w = omap_readw(OMAP_DMA_CSR(lch));
+       status = OMAP_DMA_CSR_REG(lch);
+
        /* Enable some nice interrupts. */
-       omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch));
+       OMAP_DMA_CICR_REG(lch) = dma_chan[lch].enabled_irqs;
+
        dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 }
 
-static inline void enable_lnk(int lch)
+static void omap_disable_channel_irq(int lch)
 {
-       u16 w;
+       if (cpu_is_omap24xx())
+               OMAP_DMA_CICR_REG(lch) = 0;
+}
 
-       /* Clear the STOP_LNK bits */
-       w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
-       w &= ~(1 << 14);
-       omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+void omap_enable_dma_irq(int lch, u16 bits)
+{
+       dma_chan[lch].enabled_irqs |= bits;
+}
 
-       /* And set the ENABLE_LNK bits */
+void omap_disable_dma_irq(int lch, u16 bits)
+{
+       dma_chan[lch].enabled_irqs &= ~bits;
+}
+
+static inline void enable_lnk(int lch)
+{
+       if (cpu_class_is_omap1())
+               OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 14);
+
+       /* 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));
+               OMAP_DMA_CLNK_CTRL_REG(lch) =
+                       dma_chan[lch].next_lch | (1 << 15);
 }
 
 static inline void disable_lnk(int lch)
 {
-       u16 w;
-
        /* Disable interrupts */
-       omap_writew(0, OMAP_DMA_CICR(lch));
+       if (cpu_class_is_omap1()) {
+               OMAP_DMA_CICR_REG(lch) = 0;
+               /* Set the STOP_LNK bit */
+               OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14;
+       }
 
-       /* 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));
+       if (cpu_is_omap24xx()) {
+               omap_disable_channel_irq(lch);
+               /* Clear the ENABLE_LNK bit */
+               OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15);
+       }
 
        dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
-void omap_start_dma(int lch)
+static inline void omap2_enable_irq_lch(int lch)
 {
-       u16 w;
+       u32 val;
+
+       if (!cpu_is_omap24xx())
+               return;
+
+       val = omap_readl(OMAP_DMA4_IRQENABLE_L0);
+       val |= 1 << lch;
+       omap_writel(val, OMAP_DMA4_IRQENABLE_L0);
+}
+
+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;
+
+       if (cpu_class_is_omap1())
+               clear_lch_regs(free_ch);
+
+       if (cpu_is_omap24xx())
+               omap_clear_dma(free_ch);
+
+       spin_unlock_irqrestore(&dma_chan_lock, flags);
+
+       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_omap24xx())
+               chan->enabled_irqs |= OMAP2_DMA_TRANS_ERR_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_DMA_CCR_REG(free_ch) = dev_id | (1 << 10);
+       } else if (cpu_is_omap730() || cpu_is_omap15xx()) {
+               OMAP_DMA_CCR_REG(free_ch) = dev_id;
+       }
+
+       if (cpu_is_omap24xx()) {
+               omap2_enable_irq_lch(free_ch);
+               
+               omap_enable_channel_irq(free_ch);
+               /* Clear the CSR register and IRQ status register */
+               OMAP_DMA_CSR_REG(free_ch) = 0x0;
+               omap_writel(~0x0, OMAP_DMA4_IRQSTATUS_L0);
+       }
+
+       *dma_ch_out = free_ch;
+
+       return 0;
+}
+
+void omap_free_dma(int lch)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dma_chan_lock, flags);
+       if (dma_chan[lch].dev_id == -1) {
+               printk("omap_dma: trying to free nonallocated DMA channel %d\n",
+                      lch);
+               spin_unlock_irqrestore(&dma_chan_lock, flags);
+               return;
+       }
+       dma_chan[lch].dev_id = -1;
+       dma_chan[lch].next_lch = -1;
+       dma_chan[lch].callback = NULL;
+       spin_unlock_irqrestore(&dma_chan_lock, flags);
+
+       if (cpu_class_is_omap1()) {
+               /* Disable all DMA interrupts for the channel. */
+               OMAP_DMA_CICR_REG(lch) = 0;
+               /* Make sure the DMA transfer is stopped. */
+               OMAP_DMA_CCR_REG(lch) = 0;
+       }
+
+       if (cpu_is_omap24xx()) {
+               u32 val;
+               /* Disable interrupts */
+               val = omap_readl(OMAP_DMA4_IRQENABLE_L0);
+               val &= ~(1 << lch);
+               omap_writel(val, OMAP_DMA4_IRQENABLE_L0);
+
+               /* Clear the CSR register and IRQ status register */
+               OMAP_DMA_CSR_REG(lch) = 0x0;
+
+               val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
+               val |= 1 << lch;
+               omap_writel(val, OMAP_DMA4_IRQSTATUS_L0);
+
+               /* Disable all DMA interrupts for the channel. */
+               OMAP_DMA_CICR_REG(lch) = 0;
 
+               /* Make sure the DMA transfer is stopped. */
+               OMAP_DMA_CCR_REG(lch) = 0;
+               omap_clear_dma(lch);
+       }
+}
+
+/*
+ * 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;
+
+       local_irq_save(flags);
+
+       if (cpu_class_is_omap1()) {
+               int status;
+               OMAP_DMA_CCR_REG(lch) &= ~OMAP_DMA_CCR_EN;
+
+               /* Clear pending interrupts */
+               status = OMAP_DMA_CSR_REG(lch);
+       }
+
+       if (cpu_is_omap24xx()) {
+               int i;
+               u32 lch_base = OMAP24XX_DMA_BASE + lch * 0x60 + 0x80;
+               for (i = 0; i < 0x44; i += 4)
+                       omap_writel(0, lch_base + i);
+       }
+
+       local_irq_restore(flags);
+}
+
+void omap_start_dma(int lch)
+{
        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];
@@ -348,31 +592,37 @@ void omap_start_dma(int lch)
                do {
                        next_lch = dma_chan[cur_lch].next_lch;
 
-                        /* The loop case: we've been here already */
+                       /* 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);
+                       omap_enable_channel_irq(cur_lch);
 
                        cur_lch = next_lch;
                } while (next_lch != -1);
+       } else if (cpu_is_omap24xx()) {
+               /* Errata: Need to write lch even if not using chaining */
+               OMAP_DMA_CLNK_CTRL_REG(lch) = lch;
        }
 
-       init_intr(lch);
+       omap_enable_channel_irq(lch);
+
+       /* Errata: On ES2.0 BUFFERING disable must be set.
+        * This will always fail on ES1.0 */
+       if (cpu_is_omap24xx()) {
+               OMAP_DMA_CCR_REG(lch) |= OMAP_DMA_CCR_EN;
+       }
+
+       OMAP_DMA_CCR_REG(lch) |= OMAP_DMA_CCR_EN;
 
-       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];
@@ -393,146 +643,83 @@ void omap_stop_dma(int lch)
 
                return;
        }
+
        /* Disable all interrupts on the channel */
-       omap_writew(0, OMAP_DMA_CICR(lch));
+       if (cpu_class_is_omap1())
+               OMAP_DMA_CICR_REG(lch) = 0;
 
-       w = omap_readw(OMAP_DMA_CCR(lch));
-       w &= ~OMAP_DMA_CCR_EN;
-       omap_writew(w, OMAP_DMA_CCR(lch));
+       OMAP_DMA_CCR_REG(lch) &= ~OMAP_DMA_CCR_EN;
        dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
-void omap_enable_dma_irq(int lch, u16 bits)
+/*
+ * 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)
 {
-       dma_chan[lch].enabled_irqs |= bits;
-}
+       dma_addr_t offset;
 
-void omap_disable_dma_irq(int lch, u16 bits)
-{
-       dma_chan[lch].enabled_irqs &= ~bits;
-}
+       if (cpu_class_is_omap1())
+               offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) |
+                                      (OMAP1_DMA_CSSA_U_REG(lch) << 16));
 
-static int dma_handle_ch(int ch)
-{
-       u16 csr;
+       if (cpu_is_omap24xx())
+               offset = OMAP_DMA_CSAC_REG(lch);
 
-       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 & 0x3f) == 0)
-               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;
+       return offset;
 }
 
-static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+/*
+ * 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)
 {
-       int ch = ((int) dev_id) - 1;
-       int handled = 0;
+       dma_addr_t offset;
 
-       for (;;) {
-               int handled_now = 0;
+       if (cpu_class_is_omap1())
+               offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) |
+                                      (OMAP1_DMA_CDSA_U_REG(lch) << 16));
 
-               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;
-       }
+       if (cpu_is_omap24xx())
+               offset = OMAP2_DMA_CDSA_REG(lch);
 
-       return handled ? IRQ_HANDLED : IRQ_NONE;
+       return offset;
 }
 
-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)
+/*
+ * Returns current source transfer counting for the given DMA channel.
+ * Can be used to monitor the progress of a transfer inside a block.
+ * It must be called with disabled interrupts.
+ */
+int omap_get_dma_src_addr_counter(int lch)
 {
-       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;
+       return (dma_addr_t) OMAP_DMA_CSAC_REG(lch);
 }
 
-void omap_free_dma(int ch)
+int omap_dma_running(void)
 {
-       unsigned long flags;
+       int lch;
 
-       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);
+       /* Check if LCD DMA is running */
+       if (cpu_is_omap16xx())
+               if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN)
+                       return 1;
 
-       /* 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));
-}
+       for (lch = 0; lch < dma_chan_count; lch++)
+               if (OMAP_DMA_CCR_REG(lch) & OMAP_DMA_CCR_EN)
+                       return 1;
 
-int omap_dma_in_1510_mode(void)
-{
-       return enable_1510_mode;
+       return 0;
 }
 
 /*
@@ -550,7 +737,8 @@ void omap_dma_link_lch (int lch_head, int lch_queue)
 
        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");
+               printk(KERN_ERR "omap_dma: trying to link "
+                      "non requested channels\n");
                dump_stack();
        }
 
@@ -570,20 +758,149 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue)
 
        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");
+               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");
+               printk(KERN_ERR "omap_dma: You need to stop the DMA channels "
+                      "before unlinking\n");
                dump_stack();
        }
 
        dma_chan[lch_head].next_lch = -1;
 }
 
+/*----------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP1
+
+static int omap1_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_DMA_CSR_REG(ch);
+       if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) {
+               dma_chan[ch + 6].saved_csr = csr >> 7;
+               csr &= 0x7f;
+       }
+       if ((csr & 0x3f) == 0)
+               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 omap1_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 += omap1_dma_handle_ch(ch);
+               if (enable_1510_mode && dma_chan[ch + 6].saved_csr)
+                       handled_now += omap1_dma_handle_ch(ch + 6);
+               if (!handled_now)
+                       break;
+               handled += handled_now;
+       }
+
+       return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+#else
+#define omap1_dma_irq_handler  NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+
+static int omap2_dma_handle_ch(int ch)
+{
+       u32 status = OMAP_DMA_CSR_REG(ch);
+       u32 val;
+
+       if (!status)
+               return 0;
+       if (unlikely(dma_chan[ch].dev_id == -1))
+               return 0;
+       /* REVISIT: According to 24xx TRM, there's no TOUT_IE */
+       if (unlikely(status & OMAP_DMA_TOUT_IRQ))
+               printk(KERN_INFO "DMA timeout with device %d\n",
+                      dma_chan[ch].dev_id);
+       if (unlikely(status & OMAP_DMA_DROP_IRQ))
+               printk(KERN_INFO
+                      "DMA synchronization event drop occurred with device "
+                      "%d\n", dma_chan[ch].dev_id);
+
+       if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ))
+               printk(KERN_INFO "DMA transaction error with device %d\n",
+                      dma_chan[ch].dev_id);
+
+       OMAP_DMA_CSR_REG(ch) = 0x20;
+
+       val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
+       /* ch in this function is from 0-31 while in register it is 1-32 */
+       val = 1 << (ch);
+       omap_writel(val, OMAP_DMA4_IRQSTATUS_L0);
+
+       if (likely(dma_chan[ch].callback != NULL))
+               dma_chan[ch].callback(ch, status, dma_chan[ch].data);
+
+       return 0;
+}
+
+/* STATUS register count is from 1-32 while our is 0-31 */
+static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id,
+                                        struct pt_regs *regs)
+{
+       u32 val;
+       int i;
+
+       val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
+
+       for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) {
+               int active = val & (1 << (i - 1));
+               if (active)
+                       omap2_dma_handle_ch(i - 1);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction omap24xx_dma_irq = {
+       .name = "DMA",
+       .handler = omap2_dma_irq_handler,
+       .flags = SA_INTERRUPT
+};
+
+#else
+static struct irqaction omap24xx_dma_irq;
+#endif
+
+/*----------------------------------------------------------------------------*/
 
 static struct lcd_dma_info {
        spinlock_t lock;
@@ -795,7 +1112,7 @@ static void set_b1_regs(void)
        /* Always set the source port as SDRAM for now*/
        w &= ~(0x03 << 6);
        if (lcd_dma.callback != NULL)
-               w |= 1 << 1;            /* Block interrupt enable */
+               w |= 1 << 1;            /* Block interrupt enable */
        else
                w &= ~(1 << 1);
        omap_writew(w, OMAP1610_DMA_LCD_CTRL);
@@ -814,7 +1131,8 @@ static void set_b1_regs(void)
        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)
+static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id,
+                                      struct pt_regs *regs)
 {
        u16 w;
 
@@ -870,7 +1188,8 @@ void omap_free_lcd_dma(void)
                return;
        }
        if (!enable_1510_mode)
-               omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR);
+               omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1,
+                           OMAP1610_DMA_LCD_CCR);
        lcd_dma.reserved = 0;
        spin_unlock(&lcd_dma.lock);
 }
@@ -939,93 +1258,24 @@ void omap_stop_lcd_dma(void)
        omap_writew(w, OMAP1610_DMA_LCD_CTRL);
 }
 
-/*
- * 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_readw(OMAP_DMA_CSSA_L(lch)) |
-       (omap_readw(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_readw(OMAP_DMA_CDSA_L(lch)) |
-       (omap_readw(OMAP_DMA_CDSA_U(lch)) << 16));
-}
-
-/*
- * Returns current source transfer counting for the given DMA channel.
- * Can be used to monitor the progress of a transfer inside a  block.
- * It must be called with disabled interrupts.
- */
-int omap_get_dma_src_addr_counter(int lch)
-{
-       return (dma_addr_t) omap_readw(OMAP_DMA_CSAC(lch));
-}
-
-int omap_dma_running(void)
-{
-       int lch;
-
-       /* Check if LCD DMA is running */
-       if (cpu_is_omap16xx())
-               if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN)
-                       return 1;
-
-       for (lch = 0; lch < dma_chan_count; lch++) {
-               u16 w;
-
-               w = omap_readw(OMAP_DMA_CCR(lch));
-               if (w & OMAP_DMA_CCR_EN)
-                       return 1;
-       }
-       return 0;
-}
+/*----------------------------------------------------------------------------*/
 
 static int __init omap_init_dma(void)
 {
        int ch, r;
 
-       if (cpu_is_omap1510()) {
-               printk(KERN_INFO "DMA support for OMAP1510 initialized\n");
+       if (cpu_is_omap15xx()) {
+               printk(KERN_INFO "DMA support for OMAP15xx 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_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) {
@@ -1038,6 +1288,11 @@ static int __init omap_init_dma(void)
                        dma_chan_count = 16;
                } else
                        dma_chan_count = 9;
+       } else if (cpu_is_omap24xx()) {
+               u8 revision = omap_readb(OMAP_DMA4_REVISION);
+               printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
+                      revision >> 4, revision & 0xf);
+               dma_chan_count = OMAP_LOGICAL_DMA_CH_COUNT;
        } else {
                dma_chan_count = 0;
                return 0;
@@ -1049,41 +1304,56 @@ static int __init omap_init_dma(void)
        memset(&dma_chan, 0, sizeof(dma_chan));
 
        for (ch = 0; ch < dma_chan_count; ch++) {
+               omap_clear_dma(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 (cpu_class_is_omap1()) {
+                       /* request_irq() doesn't like dev_id (ie. ch) being
+                        * zero, so we have to kludge around this. */
+                       r = request_irq(omap1_dma_irq[ch],
+                                       omap1_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",
+                                      omap1_dma_irq[ch], r);
+                               for (i = 0; i < ch; i++)
+                                       free_irq(omap1_dma_irq[i],
+                                                (void *) (i + 1));
+                               return r;
+                       }
+               }
+       }
+
+       if (cpu_is_omap24xx())
+               setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq);
+
+       /* FIXME: Update LCD DMA to work on 24xx */
+       if (cpu_class_is_omap1()) {
+               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 %d for DMA (error %d)\n",
-                              dma_irq[ch], r);
-                       for (i = 0; i < ch; i++)
-                               free_irq(dma_irq[i], (void *) (i + 1));
+                       printk(KERN_ERR "unable to request IRQ for LCD DMA "
+                              "(error %d)\n", r);
+                       for (i = 0; i < dma_chan_count; i++)
+                               free_irq(omap1_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_get_dma_src_addr_counter);
@@ -1109,6 +1379,8 @@ 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_set_dma_params);
+
 EXPORT_SYMBOL(omap_dma_link_lch);
 EXPORT_SYMBOL(omap_dma_unlink_lch);
 
diff --git a/arch/arm/plat-omap/dsp/Kconfig b/arch/arm/plat-omap/dsp/Kconfig
new file mode 100644 (file)
index 0000000..47f06b2
--- /dev/null
@@ -0,0 +1,29 @@
+
+config OMAP_DSP
+       tristate "OMAP DSP driver (DSP Gateway)"
+       depends on ARCH_OMAP15XX || ARCH_OMAP16XX
+       help
+         This enables OMAP DSP driver, DSP Gateway.
+
+config OMAP_DSP_MBCMD_VERBOSE
+       bool "Mailbox Command Verbose LOG"
+       depends on OMAP_DSP
+       help
+          This enables kernel log output in the Mailbox command exchanges
+         in the DSP Gateway driver.
+
+config OMAP_DSP_TASK_MULTIOPEN
+       bool "DSP Task Multiopen Capability"
+       depends on OMAP_DSP
+       help
+          This enables DSP tasks to be opened by multiple times at a time.
+         Otherwise, they can be opened only once at a time.
+
+config OMAP_DSP_FBEXPORT
+       bool "Framebuffer export to DSP"
+       depends on OMAP_DSP
+       help
+          This enables to map the frame buffer to DSP.
+         By doing this, DSP can access the frame buffer directly without
+         bothering ARM.
+
diff --git a/arch/arm/plat-omap/dsp/Makefile b/arch/arm/plat-omap/dsp/Makefile
new file mode 100644 (file)
index 0000000..c7d86f3
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Makefile for the OMAP DSP driver.
+#
+
+# The target object and module list name.
+
+obj-y := dsp_common.o
+
+obj-$(CONFIG_OMAP_DSP) += dsp.o
+
+# Declare multi-part drivers
+
+dsp-objs       := dsp_core.o ipbuf.o mblog.o task.o \
+                  dsp_ctl_core.o dsp_ctl.o taskwatch.o error.o dsp_mem.o \
+                  uaccess_dsp.o
diff --git a/arch/arm/plat-omap/dsp/dsp.h b/arch/arm/plat-omap/dsp/dsp.h
new file mode 100644 (file)
index 0000000..0a48766
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/dsp.h
+ *
+ * Header for OMAP DSP driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/06/09:  DSP Gateway version 3.3
+ */
+
+#include "hardware_dsp.h"
+#include "dsp_common.h"
+
+#define OLD_BINARY_SUPPORT     y
+
+#ifdef OLD_BINARY_SUPPORT
+#define MBREV_3_0      0x0017
+#define MBREV_3_2      0x0018
+#endif
+
+#define DSP_INIT_PAGE  0xfff000
+/* idle program will be placed at IDLEPG_BASE. */
+#define IDLEPG_BASE    0xfffe00
+#define IDLEPG_SIZE    0x100
+
+/* timeout value for DSP response */
+#define DSP_TIMEOUT    (10 * HZ)
+
+enum dsp_mem_type_e {
+       MEM_TYPE_CROSSING = -1,
+       MEM_TYPE_NONE = 0,
+       MEM_TYPE_DARAM,
+       MEM_TYPE_SARAM,
+       MEM_TYPE_EXTERN,
+};
+
+enum arm_dsp_dir {
+       DIR_A2D,
+       DIR_D2A,
+};
+
+/*
+ * INT_D2A_MB value definition
+ *   INT_DSP_MAILBOX1: use Mailbox 1 (INT 10) for DSP->ARM mailbox
+ *   INT_DSP_MAILBOX2: use Mailbox 2 (INT 11) for DSP->ARM mailbox
+ */
+#define INT_D2A_MB1    INT_DSP_MAILBOX1
+
+/* keep 2 entries for OMAP_DSP_TID_FREE and OMAP_DSP_TID_ANON */
+#define TASKDEV_MAX    254
+
+#define MKLONG(uw,lw)  (((unsigned long)(uw)) << 16 | (lw))
+#define MKVIRT(uw,lw)  dspword_to_virt(MKLONG((uw), (lw)));
+#define MBCMD(nm)      OMAP_DSP_MBCMD_##nm
+
+struct sync_seq {
+       unsigned short da_dsp;
+       unsigned short da_arm;
+       unsigned short ad_dsp;
+       unsigned short ad_arm;
+};
+
+struct mem_sync_struct {
+       struct sync_seq *DARAM;
+       struct sync_seq *SARAM;
+       struct sync_seq *SDRAM;
+};
+
+/* struct mbcmd and struct mbcmd_hw must be compatible */
+struct mbcmd {
+       unsigned short cmd_l:8;
+       unsigned short cmd_h:7;
+       unsigned short seq:1;
+       unsigned short data;
+};
+
+struct mbcmd_hw {
+       unsigned short cmd;
+       unsigned short data;
+};
+
+#define mbcmd_set(mb, h, l, d) \
+       do { \
+               (mb).cmd_h = (h); \
+               (mb).cmd_l = (l); \
+               (mb).data  = (d); \
+       } while(0)
+
+struct mb_exarg {
+       unsigned char tid;
+       int argc;
+       unsigned short *argv;
+};
+
+extern void dsp_mb_start(void);
+extern void dsp_mb_stop(void);
+extern int dsp_mb_config(void *p);
+extern int sync_with_dsp(unsigned short *syncwd, unsigned short tid,
+                        int try_cnt);
+extern int __mbcmd_send(struct mbcmd *mb);
+extern int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg,
+                           int recovery_flag);
+#define dsp_mbcmd_send(mb)             __dsp_mbcmd_send(mb, NULL, 0)
+#define dsp_mbcmd_send_exarg(mb, arg)  __dsp_mbcmd_send(mb, arg, 0)
+extern int __dsp_mbcmd_send_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
+                                    wait_queue_head_t *q);
+#define dsp_mbcmd_send_and_wait(mb, q) \
+       __dsp_mbcmd_send_and_wait(mb, NULL, q)
+#define dsp_mbcmd_send_and_wait_exarg(mb, arg, q) \
+       __dsp_mbcmd_send_and_wait(mb, arg, q)
+int __dsp_mbsend(unsigned char cmdh, unsigned char cmdl, unsigned short data,
+                int recovery_flag);
+#define dsp_mbsend(cmdh, cmdl, data) \
+       __dsp_mbsend(cmdh, cmdl, data, 0)
+#define dsp_mbsend_recovery(cmdh, cmdl, data) \
+       __dsp_mbsend(cmdh, cmdl, data, 1)
+
+extern void ipbuf_start(void);
+extern void ipbuf_stop(void);
+extern int ipbuf_config(unsigned short ln, unsigned short lsz, void *base);
+extern int ipbuf_sys_config(void *p, enum arm_dsp_dir dir);
+extern int ipbuf_p_validate(void *p, enum arm_dsp_dir dir);
+extern unsigned short get_free_ipbuf(unsigned char tid);
+extern void unuse_ipbuf_nowait(unsigned short bid);
+extern void unuse_ipbuf(unsigned short bid);
+extern void release_ipbuf(unsigned short bid);
+extern void balance_ipbuf(void);
+
+#define release_ipbuf_pvt(ipbuf_pvt) \
+       do { \
+               (ipbuf_pvt)->s = OMAP_DSP_TID_FREE; \
+       } while(0)
+
+extern int mbx_revision;
+
+extern int dsp_is_ready(void);
+extern int dspuncfg(void);
+extern void dsp_runlevel(unsigned char level);
+extern int dsp_suspend(void);
+extern int dsp_resume(void);
+
+extern int dsp_task_config_all(unsigned char n);
+extern void dsp_task_unconfig_all(void);
+extern unsigned char dsp_task_count(void);
+extern int dsp_taskmod_busy(void);
+extern int dsp_mkdev(char *name);
+extern int dsp_rmdev(char *name);
+extern int dsp_tadd(unsigned char minor, unsigned long adr);
+extern int dsp_tdel(unsigned char minor);
+extern int dsp_tkill(unsigned char minor);
+extern long taskdev_state_stale(unsigned char minor);
+extern int dsp_dbg_config(short *buf, unsigned short sz, unsigned short lsz);
+extern void dsp_dbg_stop(void);
+
+extern int ipbuf_is_held(unsigned char tid, unsigned short bid);
+
+extern void dsp_mem_sync_inc(void);
+extern int dsp_mem_sync_config(struct mem_sync_struct *sync);
+extern enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len);
+extern int dsp_address_validate(void *p, size_t len, char *fmt, ...);
+extern int dsp_mem_enable(void *adr);
+extern void dsp_mem_disable(void *adr);
+extern void dsp_mem_usecount_clear(void);
+extern void exmap_use(void *vadr, size_t len);
+extern void exmap_unuse(void *vadr, size_t len);
+extern unsigned long dsp_virt_to_phys(void *vadr, size_t *len);
+extern void dsp_mem_start(void);
+extern void dsp_mem_stop(void);
+
+extern void dsp_twch_start(void);
+extern void dsp_twch_stop(void);
+extern void dsp_twch_touch(void);
+
+extern void dsp_err_start(void);
+extern void dsp_err_stop(void);
+extern void dsp_err_mmu_set(unsigned long adr);
+extern void dsp_err_mmu_clear(void);
+extern int dsp_err_mmu_isset(void);
+extern void dsp_err_wdt_clear(void);
+extern int dsp_err_wdt_isset(void);
+
+enum cmd_l_type {
+       CMD_L_TYPE_NULL,
+       CMD_L_TYPE_TID,
+       CMD_L_TYPE_SUBCMD,
+};
+
+struct cmdinfo {
+       char *name;
+       enum cmd_l_type cmd_l_type;
+       void (*handler)(struct mbcmd *mb);
+};
+
+extern const struct cmdinfo *cmdinfo[];
+
+#define cmd_name(mb)   (cmdinfo[(mb).cmd_h]->name)
+extern char *subcmd_name(struct mbcmd *mb);
+
+extern void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir);
+#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
+extern void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir);
+#else /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
+#define mblog_printcmd(mb, dir)        do {} while(0)
+#endif /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
+
+#ifdef CONFIG_PROC_FS
+extern struct proc_dir_entry *procdir_dsp;
+#endif /* CONFIG_PROC_FS */
+
+extern struct platform_device dsp_device;
diff --git a/arch/arm/plat-omap/dsp/dsp_common.c b/arch/arm/plat-omap/dsp/dsp_common.c
new file mode 100644 (file)
index 0000000..88481a1
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/dsp_common.c
+ *
+ * OMAP DSP driver static part
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/06/13:  DSP Gateway version 3.3
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+#include <asm/irq.h>
+#include <asm/arch/dsp.h>
+#include <asm/arch/tc.h>
+#include <asm/hardware/clock.h>
+#include "dsp_common.h"
+
+struct clk *dsp_ck_handle;
+struct clk *api_ck_handle;
+unsigned long dspmem_base, dspmem_size,
+             daram_base, daram_size,
+             saram_base, saram_size;
+
+struct cpustat {
+       struct semaphore sem;
+       enum e_cpustat stat;
+       enum e_cpustat req;
+       unsigned short icrmask;
+       struct {
+               int mpui;
+               int mem;
+               int mem_delayed;
+       } usecount;
+       int (*mem_req_cb)(void);
+       void (*mem_rel_cb)(void);
+};
+struct cpustat cpustat = {
+       .sem = __SEMAPHORE_INIT(cpustat.sem, 1),
+       .stat = CPUSTAT_RESET,
+       .icrmask = 0xffff,
+};
+
+int dsp_set_rstvect(unsigned long adr)
+{
+       unsigned long *dst_adr;
+
+       if (adr >= DSPSPACE_SIZE)
+               return -EINVAL;
+
+       dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
+       /* word swap */
+       *dst_adr = ((adr & 0xffff) << 16) | (adr >> 16);
+       /* fill 8 bytes! */
+       *(dst_adr+1) = 0;
+       /* direct boot */
+       omap_writew(MPUI_DSP_BOOT_CONFIG_DIRECT, MPUI_DSP_BOOT_CONFIG);
+
+       return 0;
+}
+
+static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
+{
+       int i;
+       unsigned short *src = (unsigned short *)src_c;
+       int len_w;
+
+       /* len must be multiple of 2. */
+       if (len & 1)
+               BUG();
+
+       len_w = len / 2;
+       for (i = 0; i < len_w; i++) {
+               /* byte swap copy */
+               *dst = ((*src & 0x00ff) << 8) |
+                      ((*src & 0xff00) >> 8);
+               src++;
+               dst++;
+       }
+}
+
+/* program size must be multiple of 2 */
+#define GBL_IDLE_TEXT_SIZE     52
+#define GBL_IDLE_TEXT_INIT { \
+       /* SAM */ \
+       0x3c, 0x4a,                     /* 0x3c4a:     MOV 0x4, AR2 */ \
+       0xf4, 0x41, 0xfc, 0xff,         /* 0xf441fcff: AND 0xfcff, *AR2 */ \
+       /* disable WDT */ \
+       0x76, 0x34, 0x04, 0xb8,         /* 0x763404b8: MOV 0x3404, AR3 */ \
+       0xfb, 0x61, 0x00, 0xf5,         /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       0xfb, 0x61, 0x00, 0xa0,         /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       /* *IER0 = 0, *IER1 = 0 */ \
+       0x3c, 0x0b,                     /* 0x3c0b:     MOV 0x0, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
+       0x76, 0x00, 0x45, 0xb8,         /* 0x76004508: MOV 0x45, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
+       /* *ICR = 0xffff */ \
+       0x3c, 0x1b,                     /* 0x3c1b:     MOV 0x1, AR3 */ \
+       0xfb, 0x61, 0xff, 0xff,         /* 0xfb61ffff: MOV 0xffff, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       /* HOM */ \
+       0xf5, 0x41, 0x03, 0x00,         /* 0xf5410300: OR 0x0300, *AR2 */ \
+       /* idle and loop forever */ \
+       0x7a, 0x00, 0x00, 0x0c,         /* 0x7a00000c: IDLE */ \
+       0x4a, 0x7a,                     /* 0x4a7a:     B -6 (infinite loop) */ \
+       0x20, 0x20, 0x20,               /* 0x20:       NOP */ \
+}
+
+/* program size must be multiple of 2 */
+#define CPU_IDLE_TEXT_SIZE     48
+#define CPU_IDLE_TEXT_INIT(icrh, icrl) { \
+       /* SAM */ \
+       0x3c, 0x4b,                     /* 0x3c4b:     MOV 0x4, AR3 */ \
+       0xf4, 0x61, 0xfc, 0xff,         /* 0xf461fcff: AND 0xfcff, *AR3 */ \
+       /* disable WDT */ \
+       0x76, 0x34, 0x04, 0xb8,         /* 0x763404b8: MOV 0x3404, AR3 */ \
+       0xfb, 0x61, 0x00, 0xf5,         /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       0xfb, 0x61, 0x00, 0xa0,         /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       /* *IER0 = 0, *IER1 = 0 */ \
+       0x3c, 0x0b,                     /* 0x3c0b:     MOV 0x0, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
+       0x76, 0x00, 0x45, 0xb8,         /* 0x76004508: MOV 0x45, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
+       /* set ICR = icr */ \
+       0x3c, 0x1b,                     /* 0x3c1b:     MOV AR3 0x1 */ \
+       0xfb, 0x61, (icrh), (icrl),     /* 0xfb61****: MOV *AR3, icr */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       /* idle and loop forever */ \
+       0x7a, 0x00, 0x00, 0x0c,         /* 0x7a00000c: IDLE */ \
+       0x4a, 0x7a,                     /* 0x4a7a:     B -6 (infinite loop) */ \
+       0x20, 0x20, 0x20                /* 0x20: nop */ \
+}
+
+/*
+ * idle_boot base:
+ * Initialized with DSP_BOOT_ADR_MPUI (=0x010000).
+ * This value is used before DSP Gateway driver is initialized.
+ * DSP Gateway driver will overwrite this value with other value,
+ * to avoid confliction with the user program.
+ */
+static unsigned long idle_boot_base = DSP_BOOT_ADR_MPUI;
+
+static void dsp_gbl_idle(void)
+{
+       unsigned char idle_text[GBL_IDLE_TEXT_SIZE] = GBL_IDLE_TEXT_INIT;
+
+       __dsp_reset();
+       clk_use(api_ck_handle);
+
+#if 0
+       omap_writew(MPUI_DSP_BOOT_CONFIG_IDLE, MPUI_DSP_BOOT_CONFIG);
+#endif
+       simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
+                        GBL_IDLE_TEXT_SIZE);
+       if (idle_boot_base == DSP_BOOT_ADR_MPUI)
+               omap_writew(MPUI_DSP_BOOT_CONFIG_MPUI, MPUI_DSP_BOOT_CONFIG);
+       else
+               dsp_set_rstvect(idle_boot_base);
+
+       __dsp_run();
+       udelay(100);    /* to make things stable */
+       clk_unuse(api_ck_handle);
+}
+
+static void dsp_cpu_idle(void)
+{
+       unsigned short icr_tmp;
+       unsigned char icrh, icrl;
+
+       __dsp_reset();
+       clk_use(api_ck_handle);
+
+       /*
+        * icr settings:
+        * DMA should not sleep for DARAM/SARAM access
+        * DPLL should not sleep while any other domain is active
+        */
+       icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA_IDLE_DOMAIN |
+                                     DSPREG_ICR_DPLL_IDLE_DOMAIN);
+       icrh = icr_tmp >> 8;
+       icrl = icr_tmp & 0xff;
+       {
+               unsigned char idle_text[CPU_IDLE_TEXT_SIZE] = CPU_IDLE_TEXT_INIT(icrh, icrl);
+               simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
+                                CPU_IDLE_TEXT_SIZE);
+       }
+       if (idle_boot_base == DSP_BOOT_ADR_MPUI)
+               omap_writew(MPUI_DSP_BOOT_CONFIG_MPUI, MPUI_DSP_BOOT_CONFIG);
+       else
+               dsp_set_rstvect(idle_boot_base);
+       __dsp_run();
+       udelay(100);    /* to make things stable */
+       clk_unuse(api_ck_handle);
+}
+
+void dsp_set_idle_boot_base(unsigned long adr, size_t size)
+{
+       if (adr == idle_boot_base)
+               return;
+       idle_boot_base = adr;
+       if ((size < GBL_IDLE_TEXT_SIZE) ||
+           (size < CPU_IDLE_TEXT_SIZE)) {
+               printk(KERN_ERR
+                      "omapdsp: size for idle program is not enough!\n");
+               BUG();
+       }
+
+       /* restart idle program with new base address */
+       if (cpustat.stat == CPUSTAT_GBL_IDLE)
+               dsp_gbl_idle();
+       if (cpustat.stat == CPUSTAT_CPU_IDLE)
+               dsp_cpu_idle();
+}
+
+static unsigned short save_dsp_idlect2;
+static int init_done;
+
+/*
+ * note: if we are in pm_suspend / pm_resume function,
+ * we are out of clk_use() management.
+ */
+void omap_dsp_pm_suspend(void)
+{
+       unsigned short save_arm_idlect2;
+
+       /* Reset DSP */
+       __dsp_reset();
+
+       if (! init_done)
+               return;
+
+       clk_disable(dsp_ck_handle);
+
+       /* Stop any DSP domain clocks */
+       save_arm_idlect2 = omap_readw(ARM_IDLECT2); // api_ck is in ARM_IDLECT2
+       clk_enable(api_ck_handle);
+       save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
+       __raw_writew(0, DSP_IDLECT2);
+       omap_writew(save_arm_idlect2, ARM_IDLECT2);
+}
+
+void omap_dsp_pm_resume(void)
+{
+       unsigned short save_arm_idlect2;
+
+       if (! init_done)
+               return;
+
+       /* Restore DSP domain clocks */
+       save_arm_idlect2 = omap_readw(ARM_IDLECT2); // api_ck is in ARM_IDLECT2
+       clk_enable(api_ck_handle);
+       __raw_writew(save_dsp_idlect2, DSP_IDLECT2);
+       omap_writew(save_arm_idlect2, ARM_IDLECT2);
+
+       /* Run DSP, if it was running */
+       if (cpustat.stat != CPUSTAT_RESET)
+               __dsp_run();
+}
+
+static int __init omap_dsp_init(void)
+{
+       dspmem_size = 0;
+#ifdef CONFIG_ARCH_OMAP15XX
+       if (cpu_is_omap1510()) {
+               dspmem_base = OMAP1510_DSP_BASE;
+               dspmem_size = OMAP1510_DSP_SIZE;
+               daram_base = OMAP1510_DARAM_BASE;
+               daram_size = OMAP1510_DARAM_SIZE;
+               saram_base = OMAP1510_SARAM_BASE;
+               saram_size = OMAP1510_SARAM_SIZE;
+       }
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       if (cpu_is_omap16xx()) {
+               dspmem_base = OMAP16XX_DSP_BASE;
+               dspmem_size = OMAP16XX_DSP_SIZE;
+               daram_base = OMAP16XX_DARAM_BASE;
+               daram_size = OMAP16XX_DARAM_SIZE;
+               saram_base = OMAP16XX_SARAM_BASE;
+               saram_size = OMAP16XX_SARAM_SIZE;
+       }
+#endif
+       if (dspmem_size == 0) {
+               printk(KERN_ERR "omapdsp: unsupported omap architecture.\n");
+               return -ENODEV;
+       }
+
+       dsp_ck_handle = clk_get(0, "dsp_ck");
+       if (IS_ERR(dsp_ck_handle)) {
+               printk(KERN_ERR "omapdsp: could not acquire dsp_ck handle.\n");
+               return PTR_ERR(dsp_ck_handle);
+       }
+
+       api_ck_handle = clk_get(0, "api_ck");
+       if (IS_ERR(api_ck_handle)) {
+               printk(KERN_ERR "omapdsp: could not acquire api_ck handle.\n");
+               return PTR_ERR(api_ck_handle);
+       }
+
+       __dsp_enable();
+       mpui_byteswap_off();
+       mpui_wordswap_on();
+       tc_wordswap();
+
+       init_done = 1;
+       return 0;
+}
+
+static void dsp_cpustat_update(void)
+{
+       if (!init_done)
+               omap_dsp_init();
+
+       if (cpustat.req == CPUSTAT_RUN) {
+               if (cpustat.stat < CPUSTAT_RUN) {
+                       __dsp_reset();
+                       clk_use(api_ck_handle);
+                       udelay(10);
+                       __dsp_run();
+                       cpustat.stat = CPUSTAT_RUN;
+                       enable_irq(INT_DSP_MMU);
+               }
+               return;
+       }
+
+       /* cpustat.stat < CPUSTAT_RUN */
+
+       if (cpustat.stat == CPUSTAT_RUN) {
+               disable_irq(INT_DSP_MMU);
+               clk_unuse(api_ck_handle);
+       }
+
+       /*
+        * (1) when ARM wants DARAM access, MPUI should be SAM and
+        *     DSP needs to be on.
+        * (2) if any bits of icr is masked, we can not enter global idle.
+        */
+       if ((cpustat.req == CPUSTAT_CPU_IDLE) ||
+           (cpustat.usecount.mem > 0) ||
+           (cpustat.usecount.mem_delayed > 0) ||
+           ((cpustat.usecount.mpui > 0) && (cpustat.icrmask != 0xffff))) {
+               if (cpustat.stat != CPUSTAT_CPU_IDLE) {
+                       dsp_cpu_idle();
+                       cpustat.stat = CPUSTAT_CPU_IDLE;
+               }
+               return;
+       }
+
+       /*
+        * when ARM only needs MPUI access, MPUI can be HOM and
+        * DSP can be idling.
+        */
+       if ((cpustat.req == CPUSTAT_GBL_IDLE) ||
+           (cpustat.usecount.mpui > 0)) {
+               if (cpustat.stat != CPUSTAT_GBL_IDLE) {
+                       dsp_gbl_idle();
+                       cpustat.stat = CPUSTAT_GBL_IDLE;
+               }
+               return;
+       }
+
+       /*
+        * no user, no request
+        */
+       if (cpustat.stat != CPUSTAT_RESET) {
+               __dsp_reset();
+               cpustat.stat = CPUSTAT_RESET;
+       }
+}
+
+void dsp_cpustat_request(enum e_cpustat req)
+{
+       down(&cpustat.sem);
+       cpustat.req = req;
+       dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+enum e_cpustat dsp_cpustat_get_stat(void)
+{
+       return cpustat.stat;
+}
+
+unsigned short dsp_cpustat_get_icrmask(void)
+{
+       return cpustat.icrmask;
+}
+
+void dsp_cpustat_set_icrmask(unsigned short mask)
+{
+       down(&cpustat.sem);
+       cpustat.icrmask = mask;
+       dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+void omap_dsp_request_mpui(void)
+{
+       down(&cpustat.sem);
+       if (cpustat.usecount.mpui++ == 0)
+               dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+void omap_dsp_release_mpui(void)
+{
+       down(&cpustat.sem);
+       if (cpustat.usecount.mpui-- == 0) {
+               printk(KERN_ERR
+                      "omapdsp: unbalanced mpui request/release detected.\n"
+                      "         cpustat.usecount.mpui is going to be "
+                      "less than zero! ... fixed to be zero.\n");
+               cpustat.usecount.mpui = 0;
+       }
+       if (cpustat.usecount.mpui == 0)
+               dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+int omap_dsp_request_mem(void)
+{
+       int ret = 0;
+
+       down(&cpustat.sem);
+       if ((cpustat.usecount.mem++ == 0) &&
+           (cpustat.usecount.mem_delayed == 0)) {
+               if (cpustat.mem_req_cb) {
+                       if ((ret = cpustat.mem_req_cb()) < 0) {
+                               cpustat.usecount.mem--;
+                               goto out;
+                       }
+               }
+               dsp_cpustat_update();
+       }
+out:
+       up(&cpustat.sem);
+
+       return ret;
+}
+
+/*
+ * release_mem will be delayed.
+ */
+static void do_release_mem(void) {
+       down(&cpustat.sem);
+       cpustat.usecount.mem_delayed = 0;
+       if (cpustat.usecount.mem == 0) {
+               dsp_cpustat_update();
+               if (cpustat.mem_rel_cb)
+                       cpustat.mem_rel_cb();
+       }
+       up(&cpustat.sem);
+}
+
+static DECLARE_WORK(mem_rel_work, (void (*)(void *))do_release_mem, NULL);
+
+int omap_dsp_release_mem(void)
+{
+       down(&cpustat.sem);
+
+       /* cancel previous release work */
+       cancel_delayed_work(&mem_rel_work);
+       cpustat.usecount.mem_delayed = 0;
+
+       if (cpustat.usecount.mem-- == 0) {
+               printk(KERN_ERR
+                      "omapdsp: unbalanced memory request/release detected.\n"
+                      "         cpustat.usecount.mem is going to be "
+                      "less than zero! ... fixed to be zero.\n");
+               cpustat.usecount.mem = 0;
+       }
+       if (cpustat.usecount.mem == 0) {
+               cpustat.usecount.mem_delayed = 1;
+               schedule_delayed_work(&mem_rel_work, HZ);
+       }
+
+       up(&cpustat.sem);
+
+       return 0;
+}
+
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void))
+{
+       down(&cpustat.sem);
+
+       cpustat.mem_req_cb = req_cb;
+       cpustat.mem_rel_cb = rel_cb;
+
+       /*
+        * This function must be called while mem is enabled!
+        */
+       BUG_ON(cpustat.usecount.mem == 0);
+
+       up(&cpustat.sem);
+}
+
+void dsp_unregister_mem_cb(void)
+{
+       down(&cpustat.sem);
+       cpustat.mem_req_cb = NULL;
+       cpustat.mem_rel_cb = NULL;
+       up(&cpustat.sem);
+}
+
+arch_initcall(omap_dsp_init);
+
+EXPORT_SYMBOL(omap_dsp_pm_suspend);
+EXPORT_SYMBOL(omap_dsp_pm_resume);
+EXPORT_SYMBOL(omap_dsp_request_mpui);
+EXPORT_SYMBOL(omap_dsp_release_mpui);
+EXPORT_SYMBOL(omap_dsp_request_mem);
+EXPORT_SYMBOL(omap_dsp_release_mem);
+
+#ifdef CONFIG_OMAP_DSP_MODULE
+EXPORT_SYMBOL(dsp_ck_handle);
+EXPORT_SYMBOL(api_ck_handle);
+EXPORT_SYMBOL(dspmem_base);
+EXPORT_SYMBOL(dspmem_size);
+EXPORT_SYMBOL(daram_base);
+EXPORT_SYMBOL(daram_size);
+EXPORT_SYMBOL(saram_base);
+EXPORT_SYMBOL(saram_size);
+EXPORT_SYMBOL(dsp_set_rstvect);
+EXPORT_SYMBOL(dsp_set_idle_boot_base);
+EXPORT_SYMBOL(dsp_cpustat_request);
+EXPORT_SYMBOL(dsp_cpustat_get_stat);
+EXPORT_SYMBOL(dsp_cpustat_get_icrmask);
+EXPORT_SYMBOL(dsp_cpustat_set_icrmask);
+EXPORT_SYMBOL(dsp_register_mem_cb);
+EXPORT_SYMBOL(dsp_unregister_mem_cb);
+
+EXPORT_SYMBOL(__cpu_flush_kern_tlb_range);
+#endif
diff --git a/arch/arm/plat-omap/dsp/dsp_common.h b/arch/arm/plat-omap/dsp/dsp_common.h
new file mode 100644 (file)
index 0000000..36034bd
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/dsp_common.h
+ *
+ * Header for OMAP DSP driver static part
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/06/13:  DSP Gateway version 3.3
+ */
+
+#include "hardware_dsp.h"
+
+#define DSPSPACE_SIZE  0x1000000
+
+#define omap_set_bit_regw(b,r) \
+       do { omap_writew(omap_readw(r) | (b), (r)); } while(0)
+#define omap_clr_bit_regw(b,r) \
+       do { omap_writew(omap_readw(r) & ~(b), (r)); } while(0)
+#define omap_set_bit_regl(b,r) \
+       do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
+#define omap_clr_bit_regl(b,r) \
+       do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
+
+#define dspword_to_virt(dw)    ((void *)(dspmem_base + ((dw) << 1)))
+#define dspbyte_to_virt(db)    ((void *)(dspmem_base + (db)))
+#define virt_to_dspword(va)    (((unsigned long)(va) - dspmem_base) >> 1)
+#define virt_to_dspbyte(va)    ((unsigned long)(va) - dspmem_base)
+#define is_dsp_internal_mem(va) \
+       (((unsigned long)(va) >= dspmem_base) &&  \
+        ((unsigned long)(va) < dspmem_base + dspmem_size))
+#define is_dspbyte_internal_mem(db)    ((db) < dspmem_size)
+#define is_dspword_internal_mem(dw)    (((dw) << 1) < dspmem_size)
+
+/*
+ * MPUI byteswap/wordswap on/off
+ *   default setting: wordswap = all, byteswap = APIMEM only
+ */
+#define mpui_wordswap_on() \
+       do { \
+               omap_writel( \
+                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
+                       MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL); \
+       } while(0)
+
+#define mpui_wordswap_off() \
+       do { \
+               omap_writel( \
+                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
+                       MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL); \
+       } while(0)
+
+#define mpui_byteswap_on() \
+       do { \
+               omap_writel( \
+                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
+                       MPUI_CTRL_BYTESWAP_API, MPUI_CTRL); \
+       } while(0)
+
+#define mpui_byteswap_off() \
+       do { \
+               omap_writel( \
+                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
+                       MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL); \
+       } while(0)
+
+/*
+ * TC wordswap on / off
+ */
+#define tc_wordswap() \
+       do { \
+               omap_writel(TC_ENDIANISM_SWAP_WORD | TC_ENDIANISM_EN, \
+                           TC_ENDIANISM); \
+       } while(0)
+
+#define tc_noswap() \
+       do {  \
+               omap_writel(omap_readl(TC_ENDIANISM) & ~TC_ENDIANISM_EN, \
+                           TC_ENDIANISM); \
+       } while(0)
+
+/*
+ * enable priority registers, EMIF, MPUI control logic
+ */
+#define __dsp_enable() omap_set_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
+#define __dsp_disable()        omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
+#define __dsp_run()    omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
+#define __dsp_reset()  omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
+
+extern struct clk *dsp_ck_handle;
+extern struct clk *api_ck_handle;
+extern unsigned long dspmem_base, dspmem_size,
+                    daram_base, daram_size,
+                    saram_base, saram_size;
+
+enum e_cpustat {
+       CPUSTAT_RESET = 0,
+       CPUSTAT_GBL_IDLE = 1,
+       CPUSTAT_CPU_IDLE = 2,
+       CPUSTAT_RUN = 3
+};
+
+#define cpustat_name(stat) \
+       ((stat == CPUSTAT_RESET)    ? "RESET" :\
+        (stat == CPUSTAT_GBL_IDLE) ? "GBL_IDLE" :\
+        (stat == CPUSTAT_CPU_IDLE) ? "CPU_IDLE" :\
+        (stat == CPUSTAT_RUN)      ? "RUN" :\
+                                     "unknown")
+
+int dsp_set_rstvect(unsigned long adr);
+void dsp_set_idle_boot_base(unsigned long adr, size_t size);
+void dsp_cpustat_request(enum e_cpustat req);
+enum e_cpustat dsp_cpustat_get_stat(void);
+unsigned short dsp_cpustat_get_icrmask(void);
+void dsp_cpustat_set_icrmask(unsigned short mask);
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
+void dsp_unregister_mem_cb(void);
diff --git a/arch/arm/plat-omap/dsp/dsp_core.c b/arch/arm/plat-omap/dsp/dsp_core.c
new file mode 100644 (file)
index 0000000..d5d8c22
--- /dev/null
@@ -0,0 +1,781 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/dsp_core.c
+ *
+ * OMAP DSP driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/06/07:  DSP Gateway version 3.3
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/signal.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/arch/dsp.h>
+#include "hardware_dsp.h"
+#include "dsp.h"
+#include "ipbuf.h"
+
+
+MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
+MODULE_DESCRIPTION("OMAP DSP driver module");
+MODULE_LICENSE("GPL");
+
+enum mbseq_check_level {
+       MBSEQ_CHECK_NONE,       /* no check */
+       MBSEQ_CHECK_VERBOSE,    /* discard the illegal command and
+                                  error report */
+       MBSEQ_CHECK_SILENT,     /* discard the illegal command */
+};
+
+static enum mbseq_check_level mbseq_check_level = MBSEQ_CHECK_VERBOSE;
+
+static int mbx1_valid;
+static struct sync_seq *mbseq;
+static unsigned short mbseq_expect_tmp;
+static unsigned short *mbseq_expect = &mbseq_expect_tmp;
+
+/*
+ * mailbox commands
+ */
+extern void mbx1_wdsnd(struct mbcmd *mb);
+extern void mbx1_wdreq(struct mbcmd *mb);
+extern void mbx1_bksnd(struct mbcmd *mb);
+extern void mbx1_bkreq(struct mbcmd *mb);
+extern void mbx1_bkyld(struct mbcmd *mb);
+extern void mbx1_bksndp(struct mbcmd *mb);
+extern void mbx1_bkreqp(struct mbcmd *mb);
+extern void mbx1_tctl(struct mbcmd *mb);
+extern void mbx1_poll(struct mbcmd *mb);
+#ifdef OLD_BINARY_SUPPORT
+/* v3.3 obsolete */
+extern void mbx1_wdt(struct mbcmd *mb);
+#endif
+extern void mbx1_suspend(struct mbcmd *mb);
+static void mbx1_kfunc(struct mbcmd *mb);
+extern void mbx1_tcfg(struct mbcmd *mb);
+extern void mbx1_tadd(struct mbcmd *mb);
+extern void mbx1_tdel(struct mbcmd *mb);
+extern void mbx1_dspcfg(struct mbcmd *mb);
+extern void mbx1_regrw(struct mbcmd *mb);
+extern void mbx1_getvar(struct mbcmd *mb);
+extern void mbx1_err(struct mbcmd *mb);
+extern void mbx1_dbg(struct mbcmd *mb);
+
+static const struct cmdinfo
+       cif_null     = { "Unknown",  CMD_L_TYPE_NULL,   NULL         },
+       cif_wdsnd    = { "WDSND",    CMD_L_TYPE_TID,    mbx1_wdsnd   },
+       cif_wdreq    = { "WDREQ",    CMD_L_TYPE_TID,    mbx1_wdreq   },
+       cif_bksnd    = { "BKSND",    CMD_L_TYPE_TID,    mbx1_bksnd   },
+       cif_bkreq    = { "BKREQ",    CMD_L_TYPE_TID,    mbx1_bkreq   },
+       cif_bkyld    = { "BKYLD",    CMD_L_TYPE_NULL,   mbx1_bkyld   },
+       cif_bksndp   = { "BKSNDP",   CMD_L_TYPE_TID,    mbx1_bksndp  },
+       cif_bkreqp   = { "BKREQP",   CMD_L_TYPE_TID,    mbx1_bkreqp  },
+       cif_tctl     = { "TCTL",     CMD_L_TYPE_TID,    mbx1_tctl    },
+       cif_poll     = { "POLL",     CMD_L_TYPE_NULL,   mbx1_poll    },
+#ifdef OLD_BINARY_SUPPORT
+       /* v3.3 obsolete */
+       cif_wdt      = { "WDT",      CMD_L_TYPE_NULL,   mbx1_wdt     },
+#endif
+       cif_runlevel = { "RUNLEVEL", CMD_L_TYPE_SUBCMD, NULL         },
+       cif_pm       = { "PM",       CMD_L_TYPE_SUBCMD, NULL         },
+       cif_suspend  = { "SUSPEND",  CMD_L_TYPE_NULL,   mbx1_suspend },
+       cif_kfunc    = { "KFUNC",    CMD_L_TYPE_SUBCMD, mbx1_kfunc   },
+       cif_tcfg     = { "TCFG",     CMD_L_TYPE_TID,    mbx1_tcfg    },
+       cif_tadd     = { "TADD",     CMD_L_TYPE_TID,    mbx1_tadd    },
+       cif_tdel     = { "TDEL",     CMD_L_TYPE_TID,    mbx1_tdel    },
+       cif_tstop    = { "TSTOP",    CMD_L_TYPE_TID,    NULL         },
+       cif_dspcfg   = { "DSPCFG",   CMD_L_TYPE_SUBCMD, mbx1_dspcfg  },
+       cif_regrw    = { "REGRW",    CMD_L_TYPE_SUBCMD, mbx1_regrw   },
+       cif_getvar   = { "GETVAR",   CMD_L_TYPE_SUBCMD, mbx1_getvar  },
+       cif_setvar   = { "SETVAR",   CMD_L_TYPE_SUBCMD, NULL         },
+       cif_err      = { "ERR",      CMD_L_TYPE_SUBCMD, mbx1_err     },
+       cif_dbg      = { "DBG",      CMD_L_TYPE_NULL,   mbx1_dbg     };
+
+const struct cmdinfo *cmdinfo[128] = {
+/*00*/ &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+/*10*/ &cif_wdsnd, &cif_wdreq, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+/*20*/ &cif_bksnd, &cif_bkreq, &cif_null, &cif_bkyld,
+       &cif_bksndp, &cif_bkreqp, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+/*30*/ &cif_tctl, &cif_null, &cif_poll, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+/*40*/ &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+#ifdef OLD_BINARY_SUPPORT
+       /* v3.3 obsolete */
+/*50*/ &cif_wdt, &cif_runlevel, &cif_pm, &cif_suspend,
+#else
+/*50*/ &cif_null, &cif_runlevel, &cif_pm, &cif_suspend,
+#endif
+       &cif_kfunc, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+/*60*/ &cif_tcfg, &cif_null, &cif_tadd, &cif_tdel,
+       &cif_null, &cif_tstop, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null,
+/*70*/ &cif_dspcfg, &cif_null, &cif_regrw, &cif_null,
+       &cif_getvar, &cif_setvar, &cif_null, &cif_null,
+       &cif_err, &cif_dbg, &cif_null, &cif_null,
+       &cif_null, &cif_null, &cif_null, &cif_null
+};
+
+int sync_with_dsp(unsigned short *syncwd, unsigned short tid, int try_cnt)
+{
+       int try;
+
+       if (*(volatile unsigned short *)syncwd == tid)
+               return 0;
+
+       for (try = 0; try < try_cnt; try++) {
+               udelay(1);
+               if (*(volatile unsigned short *)syncwd == tid) {
+                       /* success! */
+                       printk(KERN_INFO
+                              "omapdsp: sync_with_dsp(): try = %d\n", try);
+                       return 0;
+               }
+       }
+
+       /* fail! */
+       return -1;
+}
+
+static __inline__ int mbsync_irq_save(unsigned long *flags, int try_cnt)
+{
+       int cnt;
+
+       local_irq_save(*flags);
+       if (omap_readw(MAILBOX_ARM2DSP1_Flag) == 0)
+               return 0;
+       /*
+        * mailbox is busy. wait for some usecs...
+        */
+       local_irq_restore(*flags);
+       for (cnt = 0; cnt < try_cnt; cnt++) {
+               udelay(1);
+               local_irq_save(*flags);
+               if (omap_readw(MAILBOX_ARM2DSP1_Flag) == 0)     /* success! */
+                       return 0;
+               local_irq_restore(*flags);
+       }
+
+       /* fail! */
+       return -1;
+}
+
+#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
+#define print_mb_busy_abort(mb) \
+       printk(KERN_DEBUG \
+              "mbx: mailbox is busy. %s is aborting.\n", cmd_name(*mb))
+#define print_mb_mmu_abort(mb) \
+       printk(KERN_DEBUG \
+              "mbx: mmu interrupt is set. %s is aborting.\n", cmd_name(*mb))
+#else /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
+#define print_mb_busy_abort(mb)        do {} while(0)
+#define print_mb_mmu_abort(mb) do {} while(0)
+#endif /* !CONFIG_OMAP_DSP_MBCMD_VERBOSE */
+
+int __mbcmd_send(struct mbcmd *mb)
+{
+       struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
+       unsigned long flags;
+
+       /*
+        * DSP mailbox interrupt latency must be less than 1ms.
+        */
+       if (mbsync_irq_save(&flags, 1000) < 0) {
+               print_mb_busy_abort(mb);
+               return -1;
+       }
+
+       if (mbseq) {
+               mb->seq = mbseq->ad_arm;
+               mbseq->ad_arm++;
+       } else
+               mb->seq = 0;
+       mblog_add(mb, DIR_A2D);
+       mblog_printcmd(mb, DIR_A2D);
+
+       omap_writew(mb_hw->data, MAILBOX_ARM2DSP1);
+       omap_writew(mb_hw->cmd, MAILBOX_ARM2DSP1b);
+
+       local_irq_restore(flags);
+       return 0;
+}
+
+/*
+ * __dsp_mbcmd_send(): mailbox dispatcher
+ */
+int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
+{
+       static DECLARE_MUTEX(mbsend_sem);
+       int ret = 0;
+
+       /*
+        * while MMU fault is set,
+        * only recovery command can be executed
+        */
+       if (dsp_err_mmu_isset() && !recovery_flag) {
+               print_mb_mmu_abort(mb);
+               return -1;
+       }
+
+       if (down_interruptible(&mbsend_sem) < 0)
+               return -1;
+
+       if (arg) {      /* we have extra argument */
+               int i;
+
+               /*
+                * even if ipbuf_sys_ad is in DSP internal memory, 
+                * dsp_mem_enable() never cause to call PM mailbox command
+                * because in that case DSP memory should be always enabled.
+                * (see ipbuf_sys_hold_mem_active in ipbuf.c)
+                *
+                * Therefore, we can call this function here safely.
+                */
+               dsp_mem_enable(ipbuf_sys_ad);
+               if (sync_with_dsp(&ipbuf_sys_ad->s, OMAP_DSP_TID_FREE, 10) < 0) {
+                       printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
+                       dsp_mem_disable(ipbuf_sys_ad);
+                       ret = -EBUSY;
+                       goto out;
+               }
+               for (i = 0; i < arg->argc; i++) {
+                       ipbuf_sys_ad->d[i] = arg->argv[i];
+               }
+               ipbuf_sys_ad->s = arg->tid;
+               dsp_mem_disable(ipbuf_sys_ad);
+       }
+
+       ret = __mbcmd_send(mb);
+
+out:
+       up(&mbsend_sem);
+       return ret;
+}
+
+int __dsp_mbcmd_send_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
+                             wait_queue_head_t *q)
+{
+       long current_state;
+       DECLARE_WAITQUEUE(wait, current);
+
+       add_wait_queue(q, &wait);
+       current_state = current->state;
+       set_current_state(TASK_INTERRUPTIBLE);
+       if (dsp_mbcmd_send_exarg(mb, arg) < 0) {
+               set_current_state(current_state);
+               remove_wait_queue(q, &wait);
+               return -1;
+       }
+       schedule_timeout(DSP_TIMEOUT);
+       set_current_state(current_state);
+       remove_wait_queue(q, &wait);
+
+       return 0;
+}
+
+int __dsp_mbsend(unsigned char cmdh, unsigned char cmdl, unsigned short data,
+                int recovery_flag)
+{
+       struct mbcmd mb;
+
+       mbcmd_set(mb, cmdh, cmdl, data);
+       return __dsp_mbcmd_send(&mb, NULL, recovery_flag);
+}
+
+static int mbsync_hold_mem_active;
+
+void dsp_mb_start(void)
+{
+       mbx1_valid = 1; /* start interpreting */
+       mbseq_expect_tmp = 0;
+}
+
+void dsp_mb_stop(void)
+{
+       mbx1_valid = 0; /* stop interpreting */
+       if (mbsync_hold_mem_active) {
+               dsp_mem_disable((void *)daram_base);
+               mbsync_hold_mem_active = 0;
+       }
+       mbseq = NULL;
+       mbseq_expect = &mbseq_expect_tmp;
+}
+
+int dsp_mb_config(void *p)
+{
+       unsigned long flags;
+
+       if (dsp_address_validate(p, sizeof(struct sync_seq), "mbseq") < 0)
+               return -1;
+       if (dsp_mem_type(p, sizeof(struct sync_seq)) != MEM_TYPE_EXTERN) {
+               printk(KERN_WARNING
+                      "omapdsp: mbseq is placed in DSP internal memory.\n"
+                      "         It will prevent DSP from idling.\n");
+               mbsync_hold_mem_active = 1;
+               /*
+                * dsp_mem_enable() never fails because
+                * it has been already enabled in dspcfg process and
+                * this will just increment the usecount.
+                */
+               dsp_mem_enable((void *)daram_base);
+       }
+
+       local_irq_save(flags);
+       mbseq = p;
+       mbseq->da_arm = mbseq_expect_tmp;
+       mbseq_expect = &mbseq->da_arm;
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+/*
+ * mbq: mailbox queue
+ */
+#define MBQ_DEPTH      16
+struct mbq {
+       struct mbcmd mb[MBQ_DEPTH];
+       int rp, wp, full;
+} mbq = {
+       .rp = 0,
+       .wp = 0,
+};
+
+#define mbq_inc(p)     do { if (++(p) == MBQ_DEPTH) (p) = 0; } while(0)
+
+/*
+ * workqueue for mbx1
+ */
+static void do_mbx1(void)
+{
+       int empty = 0;
+
+       disable_irq(INT_D2A_MB1);
+       if ((mbq.rp == mbq.wp) && !mbq.full)
+               empty = 1;
+       enable_irq(INT_D2A_MB1);
+
+       while (!empty) {
+               struct mbcmd *mb;
+
+               mb = &mbq.mb[mbq.rp];
+
+               mblog_add(mb, DIR_D2A);
+               mblog_printcmd(mb, DIR_D2A);
+
+               /*
+                * call handler for each command
+                */
+               if (cmdinfo[mb->cmd_h]->handler)
+                       cmdinfo[mb->cmd_h]->handler(mb);
+               else if (cmdinfo[mb->cmd_h] != &cif_null)
+                       printk(KERN_ERR "mbx: %s is not allowed from DSP.\n",
+                              cmd_name(*mb));
+               else
+                       printk(KERN_ERR
+                              "mbx: Unrecognized command: "
+                              "cmd=0x%04x, data=0x%04x\n",
+                              ((struct mbcmd_hw *)mb)->cmd & 0x7fff, mb->data);
+
+               disable_irq(INT_D2A_MB1);
+               mbq_inc(mbq.rp);
+               if (mbq.rp == mbq.wp)
+                       empty = 1;
+               /* if mbq has been full, now we have a room. */
+               if (mbq.full) {
+                       mbq.full = 0;
+                       enable_irq(INT_D2A_MB1);
+               }
+               enable_irq(INT_D2A_MB1);
+       }
+}
+
+static DECLARE_WORK(mbx1_work, (void (*)(void *))do_mbx1, NULL);
+
+/*
+ * kernel function dispatcher
+ */
+extern void mbx1_fbctl_disable(void);
+
+static void mbx1_kfunc_fbctl(unsigned short data)
+{
+       switch (data) {
+       case OMAP_DSP_MBCMD_FBCTL_DISABLE:
+               mbx1_fbctl_disable();
+               break;
+       default:
+               printk(KERN_ERR
+                      "mailbox: Unknown FBCTL from DSP: 0x%04x\n", data);
+       }
+}
+
+static void mbx1_kfunc(struct mbcmd *mb)
+{
+       switch (mb->cmd_l) {
+       case OMAP_DSP_MBCMD_KFUNC_FBCTL:
+               mbx1_kfunc_fbctl(mb->data);
+               break;
+
+       default:
+               printk(KERN_ERR
+                      "mailbox: Unknown kfunc from DSP: 0x%02x\n", mb->cmd_l);
+       }
+}
+
+/*
+ * mailbox interrupt handler
+ */
+static irqreturn_t mbx1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       union {
+               struct mbcmd sw;
+               struct mbcmd_hw hw;
+       } *mb = (void *)&mbq.mb[mbq.wp];
+
+#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
+       mb->hw.data = omap_readw(MAILBOX_DSP2ARM1);
+       mb->hw.cmd  = omap_readw(MAILBOX_DSP2ARM1b);
+#elif (INT_D2A_MB1 == INT_DSP_MAILBOX2)
+       mb->hw.data = omap_readw(MAILBOX_DSP2ARM2);
+       mb->hw.cmd  = omap_readw(MAILBOX_DSP2ARM2b);
+#endif
+
+       /* if mbx1 has not been validated yet, discard. */
+       if (!mbx1_valid)
+               return IRQ_HANDLED;
+
+       if (mb->sw.seq != (*mbseq_expect & 1)) {
+               switch (mbseq_check_level) {
+               case MBSEQ_CHECK_NONE:
+                       break;
+               case MBSEQ_CHECK_VERBOSE:
+                       printk(KERN_INFO
+                              "mbx: illegal seq bit!!!  ignoring this command."
+                              " (%04x:%04x)\n", mb->hw.cmd, mb->hw.data);
+                       return IRQ_HANDLED;
+               case MBSEQ_CHECK_SILENT:
+                       return IRQ_HANDLED;
+               }
+       }
+
+       (*mbseq_expect)++;
+
+       mbq_inc(mbq.wp);
+       if (mbq.wp == mbq.rp) { /* mbq is full */
+               mbq.full = 1;
+               disable_irq(INT_D2A_MB1);
+       }
+       schedule_work(&mbx1_work);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mbx2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned short cmd, data;
+
+#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
+       data = omap_readw(MAILBOX_DSP2ARM2);
+       cmd  = omap_readw(MAILBOX_DSP2ARM2b);
+#elif (INT_D2A_MB1 == INT_DSP_MAILBOX2)
+       data = omap_readw(MAILBOX_DSP2ARM1);
+       cmd  = omap_readw(MAILBOX_DSP2ARM1b);
+#endif
+       printk(KERN_DEBUG
+              "mailbox2 interrupt!  cmd=%04x, data=%04x\n", cmd, data);
+
+       return IRQ_HANDLED;
+}
+
+#if 0
+static void mpuio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       printk(KERN_INFO "MPUIO interrupt!\n");
+}
+#endif
+
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *procdir_dsp = NULL;
+
+static void dsp_create_procdir_dsp(void)
+{
+       procdir_dsp = proc_mkdir("dsp", 0);
+       if (procdir_dsp == NULL) {
+               printk(KERN_ERR
+                      "omapdsp: failed to register proc directory: dsp\n");
+       }
+}
+
+static void dsp_remove_procdir_dsp(void)
+{
+       procdir_dsp = NULL;
+       remove_proc_entry("dsp", 0);
+}
+#else /* CONFIG_PROC_FS */
+#define dsp_create_procdir_dsp()       do { } while (0)
+#define dsp_remove_procdir_dsp()       do { } while (0)
+#endif /* CONFIG_PROC_FS */
+
+extern irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id,
+                                    struct pt_regs *regs);
+
+extern int  dsp_ctl_core_init(void);
+extern void dsp_ctl_core_exit(void);
+extern void dsp_ctl_init(void);
+extern void dsp_ctl_exit(void);
+extern int  dsp_mem_init(void);
+extern void dsp_mem_exit(void);
+extern void mblog_init(void);
+extern void mblog_exit(void);
+extern int  dsp_taskmod_init(void);
+extern void dsp_taskmod_exit(void);
+
+/*
+ * device functions
+ */
+static void dsp_dev_release(struct device *dev)
+{
+}
+
+/*
+ * driver functions
+ */
+#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
+#      define INT_D2A_MB2 INT_DSP_MAILBOX2
+#elif(INT_D2A_MB1 == INT_DSP_MAILBOX2) /* swap MB1 and MB2 */
+#      define INT_D2A_MB2 INT_DSP_MAILBOX1
+#endif
+
+static int __init dsp_drv_probe(struct device *dev)
+{
+       int ret;
+
+       printk(KERN_INFO "OMAP DSP driver initialization\n");
+
+       //__dsp_enable(); // XXX
+
+       dsp_create_procdir_dsp();
+
+       if ((ret = dsp_ctl_core_init()) < 0)
+               goto fail1;
+       if ((ret = dsp_mem_init()) < 0)
+               goto fail2;
+       dsp_ctl_init();
+       mblog_init();
+       if ((ret = dsp_taskmod_init()) < 0)
+               goto fail3;
+
+       /*
+        * mailbox interrupt handlers registration
+        */
+       ret = request_irq(INT_D2A_MB1, mbx1_interrupt, SA_INTERRUPT, "dsp",
+                         dev);
+       if (ret) {
+               printk(KERN_ERR
+                      "failed to register mailbox1 interrupt: %d\n", ret);
+               goto fail4;
+       }
+
+       ret = request_irq(INT_D2A_MB2, mbx2_interrupt, SA_INTERRUPT, "dsp",
+                         dev);
+       if (ret) {
+               printk(KERN_ERR
+                      "failed to register mailbox2 interrupt: %d\n", ret);
+               goto fail5;
+       }
+
+       ret = request_irq(INT_DSP_MMU, dsp_mmu_interrupt, SA_INTERRUPT, "dsp",
+                         dev);
+       if (ret) {
+               printk(KERN_ERR
+                      "failed to register DSP MMU interrupt: %d\n", ret);
+               goto fail6;
+       }
+
+       /* MMU interrupt is not enabled until DSP runs */
+       disable_irq(INT_DSP_MMU);
+
+#if 0
+       ret = request_irq(INT_MPUIO, mpuio_interrupt, SA_INTERRUPT, "dsp", dev);
+       if (ret) {
+               printk(KERN_ERR
+                      "failed to register MPUIO interrupt: %d\n", ret);
+               goto fail7;
+       }
+#endif
+
+       return 0;
+
+fail6:
+       free_irq(INT_D2A_MB2, dev);
+fail5:
+       free_irq(INT_D2A_MB1, dev);
+fail4:
+       dsp_taskmod_exit();
+fail3:
+       mblog_exit();
+       dsp_ctl_exit();
+       dsp_mem_exit();
+fail2:
+       dsp_ctl_core_exit();
+fail1:
+       dsp_remove_procdir_dsp();
+
+       //__dsp_disable(); // XXX
+       return ret;
+}
+
+static int dsp_drv_remove(struct device *dev)
+{
+       dsp_cpustat_request(CPUSTAT_RESET);
+
+#if 0
+       free_irq(INT_MPUIO, dev);
+#endif
+       free_irq(INT_DSP_MMU, dev);
+       free_irq(INT_D2A_MB2, dev);
+       free_irq(INT_D2A_MB1, dev);
+
+       /* recover disable_depth */
+       enable_irq(INT_DSP_MMU);
+
+       dspuncfg();
+       dsp_taskmod_exit();
+       mblog_exit();
+       dsp_ctl_exit();
+       dsp_mem_exit();
+
+       dsp_ctl_core_exit();
+       dsp_remove_procdir_dsp();
+
+       //__dsp_disable(); // XXX
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int dsp_drv_suspend(struct device *dev, pm_message_t state)
+{
+       dsp_suspend();
+
+       return 0;
+}
+
+static int dsp_drv_resume(struct device *dev)
+{
+       dsp_resume();
+
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct resource dsp_resources[] = {
+       {
+               .start = INT_DSP_MAILBOX1,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = INT_DSP_MAILBOX2,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = INT_DSP_MMU,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device dsp_device = {
+       .name           = "dsp",
+       .id             = -1,
+       .dev = {
+               .release        = dsp_dev_release,
+       },
+       .num_resources  = ARRAY_SIZE(&dsp_resources),
+       .resource       = dsp_resources,
+};
+
+static struct device_driver dsp_driver = {
+       .name           = "dsp",
+       .bus            = &platform_bus_type,
+       .probe          = dsp_drv_probe,
+       .remove         = dsp_drv_remove,
+#ifdef CONFIG_PM
+       .suspend        = dsp_drv_suspend,
+       .resume         = dsp_drv_resume,
+#endif
+};
+
+static int __init omap_dsp_mod_init(void)
+{
+       int ret;
+
+       ret = platform_device_register(&dsp_device);
+       if (ret) {
+               printk(KERN_ERR "failed to register the DSP device: %d\n", ret);
+               goto fail1;
+       }
+
+       ret = driver_register(&dsp_driver);
+       if (ret) {
+               printk(KERN_ERR "failed to register the DSP driver: %d\n", ret);
+               goto fail2;
+       }
+
+       return 0;
+
+fail2:
+       platform_device_unregister(&dsp_device);
+fail1:
+       return -ENODEV;
+}
+
+static void __exit omap_dsp_mod_exit(void)
+{
+       driver_unregister(&dsp_driver);
+       platform_device_unregister(&dsp_device);
+}
+
+module_init(omap_dsp_mod_init);
+module_exit(omap_dsp_mod_exit);
diff --git a/arch/arm/plat-omap/dsp/dsp_ctl.c b/arch/arm/plat-omap/dsp/dsp_ctl.c
new file mode 100644 (file)
index 0000000..5738d14
--- /dev/null
@@ -0,0 +1,1015 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/dsp_ctl.c
+ *
+ * OMAP DSP control device driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/06/09:  DSP Gateway version 3.3
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/ioctls.h>
+#include <asm/hardware/clock.h>
+#include <asm/arch/dsp.h>
+#include "hardware_dsp.h"
+#include "dsp.h"
+#include "ipbuf.h"
+
+static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
+                            char *buf);
+static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
+extern struct device_attribute dev_attr_ipbuf;
+
+static enum cfgstat {
+       CFG_ERR,
+       CFG_READY,
+       CFG_SUSPEND
+} cfgstat;
+int mbx_revision;
+static DECLARE_WAIT_QUEUE_HEAD(ioctl_wait_q);
+static unsigned short ioctl_wait_cmd;
+static DECLARE_MUTEX(ioctl_sem);
+
+static unsigned char n_stask;
+
+/*
+ * control functions
+ */
+static short varread_val[5]; /* maximum */
+
+static int dsp_regread(unsigned short cmd_l, unsigned short adr,
+                      unsigned short *val)
+{
+       struct mbcmd mb;
+       int ret = 0;
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       ioctl_wait_cmd = MBCMD(REGRW);
+       mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+
+       if (ioctl_wait_cmd != 0) {
+               printk(KERN_ERR "omapdsp: register read error!\n");
+               ret = -EINVAL;
+               goto up_out;
+       }
+
+       *val = varread_val[0];
+
+up_out:
+       up(&ioctl_sem);
+       return ret;
+}
+
+static int dsp_regwrite(unsigned short cmd_l, unsigned short adr,
+                       unsigned short val)
+{
+       struct mbcmd mb;
+       struct mb_exarg arg = {
+               .tid  = OMAP_DSP_TID_ANON,
+               .argc = 1,
+               .argv = &val,
+       };
+
+       mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
+       dsp_mbcmd_send_exarg(&mb, &arg);
+       return 0;
+}
+
+static int dsp_getvar(unsigned char varid, unsigned short *val, int sz)
+{
+       struct mbcmd mb;
+       int ret = 0;
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       ioctl_wait_cmd = MBCMD(GETVAR);
+       mbcmd_set(mb, MBCMD(GETVAR), varid, 0);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+
+       if (ioctl_wait_cmd != 0) {
+               printk(KERN_ERR "omapdsp: variable read error!\n");
+               ret = -EINVAL;
+               goto up_out;
+       }
+
+       memcpy(val, varread_val, sz * sizeof(short));
+
+up_out:
+       up(&ioctl_sem);
+       return ret;
+}
+
+static int dsp_setvar(unsigned char varid, unsigned short val)
+{
+       dsp_mbsend(MBCMD(SETVAR), varid, val);
+       return 0;
+}
+
+static int dspcfg(void)
+{
+       struct mbcmd mb;
+       int ret = 0;
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       if (cfgstat != CFG_ERR) {
+               printk(KERN_ERR
+                      "omapdsp: DSP has been already configured. "
+                      "do unconfig!\n");
+               ret = -EBUSY;
+               goto up_out;
+       }
+
+       /* for safety */
+       dsp_mem_usecount_clear();
+
+       /*
+        * DSPCFG command and dsp_mem_start() must be called
+        * while internal mem is on.
+        */
+       dsp_mem_enable((void *)dspmem_base);
+
+       dsp_mb_start();
+       dsp_twch_start();
+       dsp_mem_start();
+       dsp_err_start();
+
+       mbx_revision = -1;
+       ioctl_wait_cmd = MBCMD(DSPCFG);
+       mbcmd_set(mb, MBCMD(DSPCFG), OMAP_DSP_MBCMD_DSPCFG_REQ, 0);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+
+       if (ioctl_wait_cmd != 0) {
+               printk(KERN_ERR "omapdsp: configuration error!\n");
+               ret = -EINVAL;
+               cfgstat = CFG_ERR;
+               goto up_out;
+       }
+
+#ifdef OLD_BINARY_SUPPORT
+       /*
+        * MBREV 3.2 or earlier doesn't assume DMA domain is on
+        * when DSPCFG command is sent
+        */
+       if ((mbx_revision == MBREV_3_0) ||
+           (mbx_revision == MBREV_3_2)) {
+               ret = dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
+                                DSPREG_ICR_DMA_IDLE_DOMAIN);
+       }
+#endif
+
+       if ((ret = dsp_task_config_all(n_stask)) < 0) {
+               up(&ioctl_sem);
+               dspuncfg();
+               dsp_mem_disable((void *)dspmem_base);
+               return -EINVAL;
+       }
+
+       cfgstat = CFG_READY;
+
+       /* send parameter */
+       if ((ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK,
+                             dsp_cpustat_get_icrmask())) < 0)
+               goto up_out;
+
+       /* create runtime sysfs entries */
+       device_create_file(&dsp_device.dev, &dev_attr_loadinfo);
+       device_create_file(&dsp_device.dev, &dev_attr_ipbuf);
+
+up_out:
+       dsp_mem_disable((void *)dspmem_base);
+       up(&ioctl_sem);
+       return ret;
+}
+
+int dspuncfg(void)
+{
+       if (dsp_taskmod_busy()) {
+               printk(KERN_WARNING "omapdsp: tasks are busy.\n");
+               return -EBUSY;
+       }
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       /* FIXME: lock task module */
+
+       /* remove runtime sysfs entries */
+       device_remove_file(&dsp_device.dev, &dev_attr_loadinfo);
+       device_remove_file(&dsp_device.dev, &dev_attr_ipbuf);
+
+       dsp_mb_stop();
+       dsp_twch_stop();
+       dsp_mem_stop();
+       dsp_err_stop();
+       dsp_dbg_stop();
+       dsp_task_unconfig_all();
+       ipbuf_stop();
+       cfgstat = CFG_ERR;
+
+       up(&ioctl_sem);
+       return 0;
+}
+
+int dsp_is_ready(void)
+{
+       return (cfgstat == CFG_READY) ? 1 : 0;
+}
+
+/*
+ * polls all tasks
+ */
+int dsp_poll(void)
+{
+       struct mbcmd mb;
+       int ret = 0;
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       ioctl_wait_cmd = MBCMD(POLL);
+       mbcmd_set(mb, MBCMD(POLL), 0, 0);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+
+       if (ioctl_wait_cmd != 0) {
+               printk(KERN_ERR "omapdsp: poll error!\n");
+               ret = -EINVAL;
+               goto up_out;
+       }
+
+up_out:
+       up(&ioctl_sem);
+       return ret;
+}
+
+void dsp_runlevel(unsigned char level)
+{
+       if (level == OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY)
+               dsp_mbsend_recovery(MBCMD(RUNLEVEL), level, 0);
+       else
+               dsp_mbsend(MBCMD(RUNLEVEL), level, 0);
+}
+
+static enum cfgstat cfgstat_save_suspend;
+
+/*
+ * suspend / resume callbacks
+ * DSP is not reset within this code, but done in omap_pm_suspend.
+ * so if these functions are called as OMAP_DSP_IOCTL_SUSPEND,
+ * DSP should be reset / unreset out of these functions.
+ */
+int dsp_suspend(void)
+{
+       struct mbcmd mb;
+       int ret = 0;
+
+       if (cfgstat == CFG_SUSPEND) {
+               printk(KERN_ERR "omapdsp: DSP is already in suspend state.\n");
+               return -EINVAL;
+       }
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       cfgstat_save_suspend = cfgstat;
+       if (!dsp_is_ready()) {
+               if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
+                       printk(KERN_WARNING
+                              "omapdsp: illegal operation: trying suspend DSP "
+                              "while it is running but has not configured "
+                              "yet.\n"
+                              "  Resetting DSP...\n");
+               }
+               goto transition;
+       }
+
+       ioctl_wait_cmd = MBCMD(SUSPEND);
+       mbcmd_set(mb, MBCMD(SUSPEND), 0, 0);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+
+       if (ioctl_wait_cmd != 0) {
+               printk(KERN_ERR "omapdsp: DSP suspend error!\n");
+               ret = -EINVAL;
+               goto up_out;
+       }
+
+       udelay(100);
+transition:
+       cfgstat = CFG_SUSPEND;
+up_out:
+       up(&ioctl_sem);
+       return ret;
+}
+
+int dsp_resume(void)
+{
+       if (cfgstat != CFG_SUSPEND) {
+               printk(KERN_ERR "omapdsp: DSP is not in suspend state.\n");
+               return -EINVAL;
+       }
+
+       cfgstat = cfgstat_save_suspend;
+       return 0;
+}
+
+static void dsp_fbctl_enable(void)
+{
+       dsp_mbsend(MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
+                  OMAP_DSP_MBCMD_FBCTL_ENABLE);
+}
+
+static int dsp_fbctl_disable(void)
+{
+       int ret = 0;
+       struct mbcmd mb;
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       ioctl_wait_cmd = MBCMD(KFUNC);
+       mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
+                 OMAP_DSP_MBCMD_FBCTL_DISABLE);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+       if (ioctl_wait_cmd != 0) {
+               printk(KERN_ERR "omapdsp: fb disable error!\n");
+               ret = -EINVAL;
+       }
+       up(&ioctl_sem);
+
+       return ret;
+}
+
+/*
+ * DSP control device file operations
+ */
+static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       int ret = 0;
+
+       switch (cmd) {
+       /*
+        * command level 1: commands which don't need lock
+        */
+       case OMAP_DSP_IOCTL_RUN:
+               dsp_cpustat_request(CPUSTAT_RUN);
+               break;
+
+       case OMAP_DSP_IOCTL_RESET:
+               dsp_cpustat_request(CPUSTAT_RESET);
+               break;
+
+       case OMAP_DSP_IOCTL_SETRSTVECT:
+               ret = dsp_set_rstvect((unsigned long)arg);
+               break;
+
+       case OMAP_DSP_IOCTL_CPU_IDLE:
+               dsp_cpustat_request(CPUSTAT_CPU_IDLE);
+               break;
+
+       case OMAP_DSP_IOCTL_GBL_IDLE:
+               dsp_cpustat_request(CPUSTAT_GBL_IDLE);
+               break;
+
+       case OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON:
+               mpui_wordswap_on();
+               break;
+
+       case OMAP_DSP_IOCTL_MPUI_WORDSWAP_OFF:
+               mpui_wordswap_off();
+               break;
+
+       case OMAP_DSP_IOCTL_MPUI_BYTESWAP_ON:
+               mpui_byteswap_on();
+               break;
+
+       case OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF:
+               mpui_byteswap_off();
+               break;
+
+       case OMAP_DSP_IOCTL_MBSEND:
+               {
+                       struct omap_dsp_mailbox_cmd u_cmd;
+                       struct mbcmd_hw mb;
+                       if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd)))
+                               return -EFAULT;
+                       mb.cmd  = u_cmd.cmd;
+                       mb.data = u_cmd.data;
+                       ret = dsp_mbcmd_send((struct mbcmd *)&mb);
+                       break;
+               }
+
+       case OMAP_DSP_IOCTL_SETVAR:
+               {
+                       struct omap_dsp_varinfo var;
+                       if (copy_from_user(&var, (void *)arg, sizeof(var)))
+                               return -EFAULT;
+                       ret = dsp_setvar(var.varid, var.val[0]);
+                       break;
+               }
+
+       case OMAP_DSP_IOCTL_RUNLEVEL:
+               dsp_runlevel(arg);
+               break;
+
+       case OMAP_DSP_IOCTL_FBEN:
+               dsp_fbctl_enable();
+               return 0;
+
+       /*
+        * command level 2: commands which need lock
+        */
+       case OMAP_DSP_IOCTL_DSPCFG:
+               ret = dspcfg();
+               break;
+
+       case OMAP_DSP_IOCTL_DSPUNCFG:
+               ret = dspuncfg();
+               break;
+
+       case OMAP_DSP_IOCTL_TASKCNT:
+               ret = dsp_task_count();
+               break;
+
+       case OMAP_DSP_IOCTL_POLL:
+               ret = dsp_poll();
+               break;
+
+       case OMAP_DSP_IOCTL_FBDIS:
+               ret = dsp_fbctl_disable();
+               break;
+
+       /*
+        * FIXME: cpu status control for suspend - resume
+        */
+       case OMAP_DSP_IOCTL_SUSPEND:
+               if ((ret = dsp_suspend()) < 0)
+                       break;
+               dsp_cpustat_request(CPUSTAT_RESET);
+               break;
+
+       case OMAP_DSP_IOCTL_RESUME:
+               if ((ret = dsp_resume()) < 0)
+                       break;
+               dsp_cpustat_request(CPUSTAT_RUN);
+               break;
+
+       case OMAP_DSP_IOCTL_REGMEMR:
+               {
+                       struct omap_dsp_reginfo *u_reg = (void *)arg;
+                       unsigned short adr, val;
+
+                       if (copy_from_user(&adr, &u_reg->adr, sizeof(short)))
+                               return -EFAULT;
+                       if ((ret = dsp_regread(OMAP_DSP_MBCMD_REGRW_MEMR,
+                                              adr, &val)) < 0)
+                               return ret;
+                       if (copy_to_user(&u_reg->val, &val, sizeof(short)))
+                               return -EFAULT;
+                       break;
+               }
+
+       case OMAP_DSP_IOCTL_REGMEMW:
+               {
+                       struct omap_dsp_reginfo reg;
+
+                       if (copy_from_user(&reg, (void *)arg, sizeof(reg)))
+                               return -EFAULT;
+                       ret = dsp_regwrite(OMAP_DSP_MBCMD_REGRW_MEMW,
+                                          reg.adr, reg.val);
+                       break;
+               }
+
+       case OMAP_DSP_IOCTL_REGIOR:
+               {
+                       struct omap_dsp_reginfo *u_reg = (void *)arg;
+                       unsigned short adr, val;
+
+                       if (copy_from_user(&adr, &u_reg->adr, sizeof(short)))
+                               return -EFAULT;
+                       if ((ret = dsp_regread(OMAP_DSP_MBCMD_REGRW_IOR,
+                                              adr, &val)) < 0)
+                               return ret;
+                       if (copy_to_user(&u_reg->val, &val, sizeof(short)))
+                               return -EFAULT;
+                       break;
+               }
+
+       case OMAP_DSP_IOCTL_REGIOW:
+               {
+                       struct omap_dsp_reginfo reg;
+
+                       if (copy_from_user(&reg, (void *)arg, sizeof(reg)))
+                               return -EFAULT;
+                       ret = dsp_regwrite(OMAP_DSP_MBCMD_REGRW_IOW,
+                                          reg.adr, reg.val);
+                       break;
+               }
+
+       case OMAP_DSP_IOCTL_GETVAR:
+               {
+                       struct omap_dsp_varinfo *u_var = (void *)arg;
+                       unsigned char varid;
+                       unsigned short val[5]; /* maximum */
+                       int argc;
+
+                       if (copy_from_user(&varid, &u_var->varid, sizeof(char)))
+                               return -EFAULT;
+                       switch (varid) {
+                       case OMAP_DSP_MBCMD_VARID_ICRMASK:
+                               argc = 1;
+                               break;
+                       case OMAP_DSP_MBCMD_VARID_LOADINFO:
+                               argc = 5;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+                       if ((ret = dsp_getvar(varid, val, argc)) < 0)
+                               return ret;
+                       if (copy_to_user(&u_var->val, val, sizeof(short) * argc))
+                               return -EFAULT;
+                       break;
+               }
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return ret;
+}
+
+/*
+ * functions called from mailbox1 interrupt routine
+ */
+void mbx1_suspend(struct mbcmd *mb)
+{
+       if (!waitqueue_active(&ioctl_wait_q) ||
+           (ioctl_wait_cmd != MBCMD(SUSPEND))) {
+               printk(KERN_WARNING
+                      "mbx: SUSPEND command received, "
+                      "but nobody is waiting for it...\n");
+               return;
+       }
+
+       ioctl_wait_cmd = 0;
+       wake_up_interruptible(&ioctl_wait_q);
+}
+
+void mbx1_dspcfg(struct mbcmd *mb)
+{
+       unsigned char last   = mb->cmd_l & 0x80;
+       unsigned char cfgcmd = mb->cmd_l & 0x7f;
+       static unsigned long tmp_ipb_adr;
+
+       /* mailbox protocol check */
+       if (cfgcmd == OMAP_DSP_MBCMD_DSPCFG_PROTREV) {
+               if (!waitqueue_active(&ioctl_wait_q) ||
+                   (ioctl_wait_cmd != MBCMD(DSPCFG))) {
+                       printk(KERN_WARNING
+                              "mbx: DSPCFG command received, "
+                              "but nobody is waiting for it...\n");
+                       return;
+               }
+
+               mbx_revision = mb->data;
+               if (mbx_revision == OMAP_DSP_MBPROT_REVISION)
+                       return;
+#ifdef OLD_BINARY_SUPPORT
+               else if ((mbx_revision == MBREV_3_0) ||
+                        (mbx_revision == MBREV_3_2)) {
+                       printk(KERN_WARNING
+                              "mbx: ***** old DSP binary *****\n"
+                              "  Please update your DSP application.\n");
+                       return;
+               }
+#endif
+               else {
+                       printk(KERN_ERR
+                              "mbx: protocol revision check error!\n"
+                              "  expected=0x%04x, received=0x%04x\n",
+                              OMAP_DSP_MBPROT_REVISION, mb->data);
+                       mbx_revision = -1;
+                       goto abort1;
+               }
+       }
+
+       /*
+        * following commands are accepted only after
+        * revision check has been passed.
+        */
+       if (!mbx_revision < 0) {
+               printk(KERN_INFO
+                      "mbx: DSPCFG command received, "
+                      "but revision check has not been passed.\n");
+               return;
+       }
+
+       if (!waitqueue_active(&ioctl_wait_q) ||
+           (ioctl_wait_cmd != MBCMD(DSPCFG))) {
+               printk(KERN_WARNING
+                      "mbx: DSPCFG command received, "
+                      "but nobody is waiting for it...\n");
+               return;
+       }
+
+       switch (cfgcmd) {
+       case OMAP_DSP_MBCMD_DSPCFG_SYSADRH:
+               tmp_ipb_adr = (unsigned long)mb->data << 16;
+               break;
+
+       case OMAP_DSP_MBCMD_DSPCFG_SYSADRL:
+               tmp_ipb_adr |= mb->data;
+               break;
+
+       case OMAP_DSP_MBCMD_DSPCFG_ABORT:
+               goto abort1;
+
+       default:
+               printk(KERN_ERR
+                      "mbx: Unknown CFG command: cmd_l=0x%02x, data=0x%04x\n",
+                      mb->cmd_l, mb->data);
+               return;
+       }
+
+       if (last) {
+               void *badr;
+               unsigned short bln;
+               unsigned short bsz;
+               volatile unsigned short *buf;
+               void *ipb_sys_da, *ipb_sys_ad;
+               void *mbseq;
+               short *dbg_buf;
+               unsigned short dbg_buf_sz, dbg_line_sz;
+               struct mem_sync_struct mem_sync, *mem_syncp;
+
+               ipb_sys_da = dspword_to_virt(tmp_ipb_adr);
+               if (ipbuf_sys_config(ipb_sys_da, DIR_D2A) < 0)
+                       goto abort1;
+
+               if (sync_with_dsp(&ipbuf_sys_da->s, OMAP_DSP_TID_ANON, 10) < 0) {
+                       printk(KERN_ERR "mbx: DSPCFG - IPBUF sync failed!\n");
+                       goto abort1;
+               }
+               /*
+                * read configuration data on system IPBUF
+                * we must read with 16bit-access
+                */
+#ifdef OLD_BINARY_SUPPORT
+               if (mbx_revision == OMAP_DSP_MBPROT_REVISION) {
+#endif
+                       buf = ipbuf_sys_da->d;
+                       n_stask        = buf[0];
+                       bln            = buf[1];
+                       bsz            = buf[2];
+                       badr           = MKVIRT(buf[3], buf[4]);
+                       /* ipb_sys_da     = MKVIRT(buf[5], buf[6]); */
+                       ipb_sys_ad     = MKVIRT(buf[7], buf[8]);
+                       mbseq          = MKVIRT(buf[9], buf[10]);
+                       dbg_buf        = MKVIRT(buf[11], buf[12]);
+                       dbg_buf_sz     = buf[13];
+                       dbg_line_sz    = buf[14];
+                       mem_sync.DARAM = MKVIRT(buf[15], buf[16]);
+                       mem_sync.SARAM = MKVIRT(buf[17], buf[18]);
+                       mem_sync.SDRAM = MKVIRT(buf[19], buf[20]);
+                       mem_syncp = &mem_sync;
+#ifdef OLD_BINARY_SUPPORT
+               } else if (mbx_revision == MBREV_3_2) {
+                       buf = ipbuf_sys_da->d;
+                       n_stask     = buf[0];
+                       bln         = buf[1];
+                       bsz         = buf[2];
+                       badr        = MKVIRT(buf[3], buf[4]);
+                       /* ipb_sys_da  = MKVIRT(buf[5], buf[6]); */
+                       ipb_sys_ad  = MKVIRT(buf[7], buf[8]);
+                       mbseq       = MKVIRT(buf[9], buf[10]);
+                       dbg_buf     = NULL;
+                       dbg_buf_sz  = 0;
+                       dbg_line_sz = 0;
+                       mem_syncp   = NULL;
+               } else if (mbx_revision == MBREV_3_0) {
+                       buf = ipbuf_sys_da->d;
+                       n_stask     = buf[0];
+                       bln         = buf[1];
+                       bsz         = buf[2];
+                       badr        = MKVIRT(buf[3], buf[4]);
+                       /* bkeep       = buf[5]; */
+                       /* ipb_sys_da  = MKVIRT(buf[6], buf[7]); */
+                       ipb_sys_ad  = MKVIRT(buf[8], buf[9]);
+                       mbseq       = MKVIRT(buf[10], buf[11]);
+                       dbg_buf     = NULL;
+                       dbg_buf_sz  = 0;
+                       dbg_line_sz = 0;
+                       mem_syncp   = NULL;
+               } else /* should not occur */
+                       goto abort1;
+#endif /* OLD_BINARY_SUPPORT */
+
+               release_ipbuf_pvt(ipbuf_sys_da);
+
+               /*
+                * following configurations need to be done before
+                * waking up the dspcfg initiator process.
+                */
+               if (ipbuf_sys_config(ipb_sys_ad, DIR_A2D) < 0)
+                       goto abort1;
+               if (ipbuf_config(bln, bsz, badr) < 0)
+                       goto abort1;
+               if (dsp_mb_config(mbseq) < 0)
+                       goto abort2;
+               if (dsp_dbg_config(dbg_buf, dbg_buf_sz, dbg_line_sz) < 0)
+                       goto abort2;
+               if (dsp_mem_sync_config(mem_syncp) < 0)
+                       goto abort2;
+
+               ioctl_wait_cmd = 0;
+               wake_up_interruptible(&ioctl_wait_q);
+       }
+       return;
+
+abort2:
+       ipbuf_stop();
+abort1:
+       wake_up_interruptible(&ioctl_wait_q);
+       return;
+}
+
+void mbx1_poll(struct mbcmd *mb)
+{
+       if (!waitqueue_active(&ioctl_wait_q) ||
+           (ioctl_wait_cmd != MBCMD(POLL))) {
+               printk(KERN_WARNING
+                      "mbx: POLL command received, "
+                      "but nobody is waiting for it...\n");
+               return;
+       }
+
+       ioctl_wait_cmd = 0;
+       wake_up_interruptible(&ioctl_wait_q);
+}
+
+void mbx1_regrw(struct mbcmd *mb)
+{
+       if (!waitqueue_active(&ioctl_wait_q) ||
+           (ioctl_wait_cmd != MBCMD(REGRW))) {
+               printk(KERN_WARNING
+                      "mbx: REGRW command received, "
+                      "but nobody is waiting for it...\n");
+               return;
+       }
+
+       switch (mb->cmd_l) {
+       case OMAP_DSP_MBCMD_REGRW_DATA:
+               ioctl_wait_cmd = 0;
+               varread_val[0] = mb->data;
+               wake_up_interruptible(&ioctl_wait_q);
+               return;
+
+       default:
+               printk(KERN_ERR
+                      "mbx: Illegal REGRW command: "
+                      "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
+               return;
+       }
+}
+
+void mbx1_getvar(struct mbcmd *mb)
+{
+       unsigned char varid = mb->cmd_l;
+       int i;
+       volatile unsigned short *buf;
+
+       if (!waitqueue_active(&ioctl_wait_q) ||
+           (ioctl_wait_cmd != MBCMD(GETVAR))) {
+               printk(KERN_WARNING
+                      "mbx: GETVAR command received, "
+                      "but nobody is waiting for it...\n");
+               return;
+       }
+
+       ioctl_wait_cmd = 0;
+       switch (varid) {
+       case OMAP_DSP_MBCMD_VARID_ICRMASK:
+               varread_val[0] = mb->data;
+               break;
+       case OMAP_DSP_MBCMD_VARID_LOADINFO:
+               {
+                       if (sync_with_dsp(&ipbuf_sys_da->s, OMAP_DSP_TID_ANON, 10) < 0) {
+                               printk(KERN_ERR
+                                      "mbx: GETVAR - IPBUF sync failed!\n");
+                               return;
+                       }
+                       /* need word access. do not use memcpy. */
+                       buf = ipbuf_sys_da->d;
+                       for (i = 0; i < 5; i++) {
+                               varread_val[i] = buf[i];
+                       }
+                       release_ipbuf_pvt(ipbuf_sys_da);
+                       break;
+               }
+       }
+       wake_up_interruptible(&ioctl_wait_q);
+
+       return;
+}
+
+/*
+ * sysfs files
+ */
+static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       int len = 0;
+
+       /*
+        * I/F VERSION descriptions:
+        *
+        * 3.2: sysfs / udev support
+        *      KMEM_RESERVE / KMEM_RELEASE ioctls for mem device
+        * 3.3: added following ioctls
+        *      OMAP_DSP_IOCTL_GBL_IDLE
+        *      OMAP_DSP_IOCTL_CPU_IDLE (instead of OMAP_DSP_IOCTL_IDLE)
+        *      OMAP_DSP_IOCTL_POLL
+        */
+
+       /*
+        * print all supporting I/F VERSIONs, like followings.
+        *
+        * len += sprintf(buf, "3.2\n");
+        * len += sprintf(buf, "3.3\n");
+        */
+       len += sprintf(buf + len, "3.2\n");
+       len += sprintf(buf + len, "3.3\n");
+
+       return len;
+}
+
+static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
+
+static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       return sprintf(buf, "%s\n", cpustat_name(dsp_cpustat_get_stat()));
+}
+
+static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
+
+static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       return sprintf(buf, "0x%04x\n", dsp_cpustat_get_icrmask());
+}
+
+static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
+{
+       unsigned short mask;
+       int ret;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       mask = simple_strtol(buf, NULL, 16);
+       dsp_cpustat_set_icrmask(mask);
+
+       if (dsp_is_ready()) {
+               ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK, mask);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return strlen(buf);
+}
+
+static struct device_attribute dev_attr_icrmask = 
+       __ATTR(icrmask, S_IWUSR | S_IRUGO, icrmask_show, icrmask_store);
+
+static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       int len;
+       int ret;
+       static unsigned short val[5];
+
+       if ((ret = dsp_getvar(OMAP_DSP_MBCMD_VARID_LOADINFO, val, 5)) < 0)
+               return ret;
+
+       /* load info value range is 0(free) - 10000(busy) */
+       len = sprintf(buf,
+                     "DSP load info:\n"
+                     "  10ms average = %3d.%02d%%\n"
+                     "  1sec average = %3d.%02d%%  busiest 10ms = %3d.%02d%%\n"
+                     "  1min average = %3d.%02d%%  busiest 1s   = %3d.%02d%%\n",
+                     val[0]/100, val[0]%100,
+                     val[1]/100, val[1]%100, val[2]/100, val[2]%100,
+                     val[3]/100, val[3]%100, val[4]/100, val[4]%100);
+       return len;
+}
+
+/*
+ * This is declared at the top of this file.
+ *
+ * static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
+ */
+
+void mbx1_fbctl_disable(void)
+{
+       if (!waitqueue_active(&ioctl_wait_q) ||
+           (ioctl_wait_cmd != MBCMD(KFUNC))) {
+               printk(KERN_WARNING
+                      "mbx: KFUNC:FBCTL command received, "
+                      "but nobody is waiting for it...\n");
+               return;
+       }
+       ioctl_wait_cmd = 0;
+       wake_up_interruptible(&ioctl_wait_q);
+}
+
+#ifdef CONFIG_PROC_FS
+/* for backward compatibility */
+static int version_read_proc(char *page, char **start, off_t off, int count,
+                            int *eof, void *data)
+{
+       /*
+        * This entry is read by 3.1 tools only, so leave it as is.
+        * 3.2 and later will read from sysfs file.
+        */
+       return sprintf(page, "3.1\n");
+}
+
+static void __init dsp_ctl_create_proc(void)
+{
+       struct proc_dir_entry *ent;
+
+       /* version */
+       ent = create_proc_read_entry("version", 0, procdir_dsp,
+                                    version_read_proc, NULL);
+       if (ent == NULL) {
+               printk(KERN_ERR
+                      "omapdsp: failed to register proc device: version\n");
+       }
+}
+
+static void dsp_ctl_remove_proc(void)
+{
+       remove_proc_entry("version", procdir_dsp);
+}
+#endif /* CONFIG_PROC_FS */
+
+struct file_operations dsp_ctl_fops = {
+       .owner   = THIS_MODULE,
+       .ioctl   = dsp_ctl_ioctl,
+};
+
+void __init dsp_ctl_init(void)
+{
+       device_create_file(&dsp_device.dev, &dev_attr_ifver);
+       device_create_file(&dsp_device.dev, &dev_attr_cpustat);
+       device_create_file(&dsp_device.dev, &dev_attr_icrmask);
+#ifdef CONFIG_PROC_FS
+       dsp_ctl_create_proc();
+#endif
+}
+
+void dsp_ctl_exit(void)
+{
+       device_remove_file(&dsp_device.dev, &dev_attr_ifver);
+       device_remove_file(&dsp_device.dev, &dev_attr_cpustat);
+       device_remove_file(&dsp_device.dev, &dev_attr_icrmask);
+#ifdef CONFIG_PROC_FS
+       dsp_ctl_remove_proc();
+#endif
+}
diff --git a/arch/arm/plat-omap/dsp/dsp_ctl_core.c b/arch/arm/plat-omap/dsp/dsp_ctl_core.c
new file mode 100644 (file)
index 0000000..8207441
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/dsp_ctl_core.c
+ *
+ * OMAP DSP control devices core driver
+ *
+ * Copyright (C) 2004,2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/07/26:  DSP Gateway version 3.3
+ */
+
+#include <linux/module.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <asm/arch/dsp.h>
+#include "hardware_dsp.h"
+
+#define CTL_MINOR      0
+#define MEM_MINOR      1
+#define TWCH_MINOR     2
+#define ERR_MINOR      3
+
+static struct class *dsp_ctl_class;
+extern struct file_operations dsp_ctl_fops,
+                             dsp_mem_fops,
+                             dsp_twch_fops,
+                             dsp_err_fops;
+
+static int dsp_ctl_core_open(struct inode *inode, struct file *file)
+{
+       switch (iminor(inode)) {
+       case CTL_MINOR:
+               file->f_op = &dsp_ctl_fops;
+               break;
+       case MEM_MINOR:
+               file->f_op = &dsp_mem_fops;
+               break;
+       case TWCH_MINOR:
+               file->f_op = &dsp_twch_fops;
+               break;
+       case ERR_MINOR:
+               file->f_op = &dsp_err_fops;
+               break;
+       default:
+               return -ENXIO;
+       }
+       if (file->f_op && file->f_op->open)
+               return file->f_op->open(inode, file);
+       return 0;
+}
+
+static struct file_operations dsp_ctl_core_fops = {
+       .owner = THIS_MODULE,
+       .open  = dsp_ctl_core_open,
+};
+
+static const struct dev_list {
+       unsigned int    minor;
+       char            *devname;
+       umode_t         mode;
+} dev_list[] = {
+       {CTL_MINOR,  "dspctl",  S_IRUSR | S_IWUSR},
+       {MEM_MINOR,  "dspmem",  S_IRUSR | S_IWUSR | S_IRGRP},
+       {TWCH_MINOR, "dsptwch", S_IRUSR | S_IWUSR | S_IRGRP},
+       {ERR_MINOR,  "dsperr",  S_IRUSR | S_IRGRP},
+};
+
+int __init dsp_ctl_core_init(void)
+{
+       int retval;
+       int i;
+       struct class_device *cdev;
+
+       retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl",
+                                &dsp_ctl_core_fops);
+       if (retval < 0) {
+               printk(KERN_ERR
+                      "omapdsp: failed to register dspctl device: %d\n",
+                      retval);
+               return retval;
+       }
+
+       dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
+       for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
+               cdev = class_device_create(dsp_ctl_class, NULL,
+                                   MKDEV(OMAP_DSP_CTL_MAJOR,
+                                         dev_list[i].minor),
+                                   NULL, dev_list[i].devname);
+       }
+
+       return 0;
+}
+
+void dsp_ctl_core_exit(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
+               class_device_destroy(dsp_ctl_class,
+                                    MKDEV(OMAP_DSP_CTL_MAJOR,
+                                          dev_list[i].minor));
+       }
+       class_destroy(dsp_ctl_class);
+
+       unregister_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl");
+}
diff --git a/arch/arm/plat-omap/dsp/dsp_mem.c b/arch/arm/plat-omap/dsp/dsp_mem.c
new file mode 100644 (file)
index 0000000..fbce6eb
--- /dev/null
@@ -0,0 +1,1755 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/dsp_mem.c
+ *
+ * OMAP DSP memory driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * 2005/06/09:  DSP Gateway version 3.3
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/ioctls.h>
+#include <asm/irq.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/hardware/clock.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/dsp.h>
+#include <asm/arch/dsp_common.h>
+#include "uaccess_dsp.h"
+#include "dsp.h"
+
+#define SZ_1MB 0x100000
+#define SZ_64KB        0x10000
+#define SZ_4KB 0x1000
+#define SZ_1KB 0x400
+#define is_aligned(adr,align)  (!((adr)&((align)-1)))
+#define ORDER_1MB      (20 - PAGE_SHIFT)
+#define ORDER_64KB     (16 - PAGE_SHIFT)
+#define ORDER_4KB      (12 - PAGE_SHIFT)
+
+#define PGDIR_MASK             (~(PGDIR_SIZE-1))
+#define PGDIR_ALIGN(addr)      (((addr)+PGDIR_SIZE-1)&(PGDIR_MASK))
+
+#define dsp_mmu_enable() \
+       do { \
+               omap_writew(DSPMMU_CNTL_MMU_EN | DSPMMU_CNTL_RESET_SW, \
+                           DSPMMU_CNTL); \
+       } while(0)
+#define dsp_mmu_disable() \
+       do { omap_writew(0, DSPMMU_CNTL); } while(0)
+#define dsp_mmu_flush() \
+       do { \
+               omap_writew(DSPMMU_FLUSH_ENTRY_FLUSH_ENTRY, \
+                           DSPMMU_FLUSH_ENTRY); \
+       } while(0)
+#define __dsp_mmu_gflush() \
+       do { omap_writew(DSPMMU_GFLUSH_GFLUSH, DSPMMU_GFLUSH); } while(0)
+#define __dsp_mmu_itack() \
+       do { omap_writew(DSPMMU_IT_ACK_IT_ACK, DSPMMU_IT_ACK); } while(0)
+
+#define EMIF_PRIO_LB_MASK      0x0000f000
+#define EMIF_PRIO_LB_SHIFT     12
+#define EMIF_PRIO_DMA_MASK     0x00000f00
+#define EMIF_PRIO_DMA_SHIFT    8
+#define EMIF_PRIO_DSP_MASK     0x00000070
+#define EMIF_PRIO_DSP_SHIFT    4
+#define EMIF_PRIO_MPU_MASK     0x00000007
+#define EMIF_PRIO_MPU_SHIFT    0
+#define set_emiff_dma_prio(prio) \
+       do { \
+               omap_writel((omap_readl(OMAP_TC_OCPT1_PRIOR) & \
+       ~EMIF_PRIO_DMA_MASK) | \
+                           ((prio) << EMIF_PRIO_DMA_SHIFT), \
+                           OMAP_TC_OCPT1_PRIOR); \
+       } while(0)
+
+enum exmap_type {
+       EXMAP_TYPE_MEM,
+       EXMAP_TYPE_FB
+};
+
+struct exmap_tbl {
+       unsigned int valid:1;
+       unsigned int cntnu:1;   /* grouping */
+       int usecount;           /* reference count by mmap */
+       enum exmap_type type;
+       void *buf;              /* virtual address of the buffer,
+                                * i.e. 0xc0000000 - */
+       void *vadr;             /* DSP shadow space,
+                                * i.e. 0xe0000000 - 0xe0ffffff */
+       unsigned int order;
+};
+#define DSPMMU_TLB_LINES       32
+static struct exmap_tbl exmap_tbl[DSPMMU_TLB_LINES];
+static DECLARE_RWSEM(exmap_sem);
+
+static int dsp_exunmap(unsigned long dspadr);
+
+static void *dspvect_page;
+static unsigned long dsp_fault_adr;
+static struct mem_sync_struct mem_sync;
+
+static __inline__ unsigned long lineup_offset(unsigned long adr,
+                                             unsigned long ref,
+                                             unsigned long mask)
+{
+       unsigned long newadr;
+
+       newadr = (adr & ~mask) | (ref & mask);
+       if (newadr < adr)
+               newadr += mask + 1;
+       return newadr;
+}
+
+void dsp_mem_sync_inc(void)
+{
+       /*
+        * FIXME: dsp_mem_enable()!!!
+        */
+       if (mem_sync.DARAM)
+               mem_sync.DARAM->ad_arm++;
+       if (mem_sync.SARAM)
+               mem_sync.SARAM->ad_arm++;
+       if (mem_sync.SDRAM)
+               mem_sync.SDRAM->ad_arm++;
+}
+
+/*
+ * dsp_mem_sync_config() is called from mbx1 workqueue
+ */
+int dsp_mem_sync_config(struct mem_sync_struct *sync)
+{
+       size_t sync_seq_sz = sizeof(struct sync_seq);
+
+#ifdef OLD_BINARY_SUPPORT
+       if (sync == NULL) {
+               memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
+               return 0;
+       }
+#endif
+       if ((dsp_mem_type(sync->DARAM, sync_seq_sz) != MEM_TYPE_DARAM) ||
+           (dsp_mem_type(sync->SARAM, sync_seq_sz) != MEM_TYPE_SARAM) ||
+           (dsp_mem_type(sync->SDRAM, sync_seq_sz) != MEM_TYPE_EXTERN)) {
+               printk(KERN_ERR
+                      "omapdsp: mem_sync address validation failure!\n"
+                      "  mem_sync.DARAM = 0x%p,\n"
+                      "  mem_sync.SARAM = 0x%p,\n"
+                      "  mem_sync.SDRAM = 0x%p,\n",
+                      sync->DARAM, sync->SARAM, sync->SDRAM);
+               return -1;
+       }
+       memcpy(&mem_sync, sync, sizeof(struct mem_sync_struct));
+       return 0;
+}
+
+/*
+ * kmem_reserve(), kmem_release():
+ * reserve or release kernel memory for exmap().
+ *
+ * exmap() might request consecutive 1MB or 64kB,
+ * but it will be difficult after memory pages are fragmented.
+ * So, user can reserve such memory blocks in the early phase
+ * through kmem_reserve().
+ */
+struct kmem_pool {
+       struct semaphore sem;
+       unsigned long buf[16];
+       int count;
+};
+
+#define KMEM_POOL_INIT(name) \
+{ \
+       .sem = __SEMAPHORE_INIT((name).sem, 1), \
+}
+#define DECLARE_KMEM_POOL(name) \
+       struct kmem_pool name = KMEM_POOL_INIT(name)
+
+DECLARE_KMEM_POOL(kmem_pool_1M);
+DECLARE_KMEM_POOL(kmem_pool_64K);
+
+static void dsp_kmem_release(void)
+{
+       int i;
+
+       down(&kmem_pool_1M.sem);
+       for (i = 0; i < kmem_pool_1M.count; i++) {
+               if (kmem_pool_1M.buf[i])
+                       free_pages(kmem_pool_1M.buf[i], ORDER_1MB);
+       }
+       kmem_pool_1M.count = 0;
+       up(&kmem_pool_1M.sem);
+
+       down(&kmem_pool_64K.sem);
+       for (i = 0; i < kmem_pool_64K.count; i++) {
+               if (kmem_pool_64K.buf[i])
+                       free_pages(kmem_pool_64K.buf[i], ORDER_64KB);
+       }
+       kmem_pool_64K.count = 0;
+       up(&kmem_pool_1M.sem);
+}
+
+static int dsp_kmem_reserve(unsigned long size)
+{
+       unsigned long buf;
+       unsigned int order;
+       unsigned long unit;
+       unsigned long _size;
+       struct kmem_pool *pool;
+       int i;
+
+       /* alignment check */
+       if (!is_aligned(size, SZ_64KB)) {
+               printk(KERN_ERR
+                      "omapdsp: size(0x%lx) is not multiple of 64KB.\n", size);
+               return -EINVAL;
+       }
+       if (size > DSPSPACE_SIZE) {
+               printk(KERN_ERR
+                      "omapdsp: size(0x%lx) is larger than DSP memory space "
+                      "size (0x%x.\n", size, DSPSPACE_SIZE);
+               return -EINVAL;
+       }
+
+       for (_size = size; _size; _size -= unit) {
+               if (_size >= SZ_1MB) {
+                       unit = SZ_1MB;
+                       order = ORDER_1MB;
+                       pool = &kmem_pool_1M;
+               } else {
+                       unit = SZ_64KB;
+                       order = ORDER_64KB;
+                       pool = &kmem_pool_64K;
+               }
+
+               buf = __get_dma_pages(GFP_KERNEL, order);
+               if (!buf)
+                       return size - _size;
+               down(&pool->sem);
+               for (i = 0; i < 16; i++) {
+                       if (!pool->buf[i]) {
+                               pool->buf[i] = buf;
+                               pool->count++;
+                               buf = 0;
+                               break;
+                       }
+               }
+               up(&pool->sem);
+
+               if (buf) {      /* pool is full */
+                       free_pages(buf, order);
+                       return size - _size;
+               }
+       }
+
+       return size;
+}
+
+static unsigned long dsp_mem_get_dma_pages(unsigned int order)
+{
+       struct kmem_pool *pool;
+       unsigned long buf = 0;
+       int i;
+
+       switch (order) {
+               case ORDER_1MB:
+                       pool = &kmem_pool_1M;
+                       break;
+               case ORDER_64KB:
+                       pool = &kmem_pool_64K;
+                       break;
+               default:
+                       pool = NULL;
+       }
+
+       if (pool) {
+               down(&pool->sem);
+               for (i = 0; i < pool->count; i++) {
+                       if (pool->buf[i]) {
+                               buf = pool->buf[i];
+                               pool->buf[i] = 0;
+                               break;
+                       }
+               }
+               up(&pool->sem);
+               if (buf)
+                       return buf;
+       }
+
+       /* other size or not found in pool */
+       return __get_dma_pages(GFP_KERNEL, order);
+}
+
+static void dsp_mem_free_pages(unsigned long buf, unsigned int order)
+{
+       struct kmem_pool *pool;
+       struct page *page, *ps, *pe;
+       int i;
+
+       ps = virt_to_page(buf);
+       pe = virt_to_page(buf + (1 << (PAGE_SHIFT + order)));
+       for (page = ps; page < pe; page++) {
+               ClearPageReserved(page);
+       }
+
+       /*
+        * return buffer to kmem_pool or paging system
+        */
+       switch (order) {
+               case ORDER_1MB:
+                       pool = &kmem_pool_1M;
+                       break;
+               case ORDER_64KB:
+                       pool = &kmem_pool_64K;
+                       break;
+               default:
+                       pool = NULL;
+       }
+
+       if (pool) {
+               down(&pool->sem);
+               for (i = 0; i < pool->count; i++) {
+                       if (!pool->buf[i]) {
+                               pool->buf[i] = buf;
+                               buf = 0;
+                       }
+               }
+               up(&pool->sem);
+       }
+
+       /* other size or pool is filled */
+       if (buf)
+               free_pages(buf, order);
+}
+
+/*
+ * ARM MMU operations
+ */
+static int exmap_set_armmmu(unsigned long virt, unsigned long phys,
+                           unsigned long size)
+{
+       long off;
+       unsigned long sz_left;
+       pmd_t *pmdp;
+       pte_t *ptep;
+       int prot_pmd, prot_pte;
+
+       printk(KERN_DEBUG
+              "omapdsp: mapping in ARM MMU, v=0x%08lx, p=0x%08lx, sz=0x%lx\n",
+              virt, phys, size);
+
+       prot_pmd = PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_IO);
+       prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE;
+
+       pmdp = pmd_offset(pgd_offset_k(virt), virt);
+       if (pmd_none(*pmdp)) {
+               ptep = pte_alloc_one_kernel(&init_mm, 0);
+               if (ptep == NULL)
+                       return -ENOMEM;
+               /* note: two PMDs will be set  */
+               pmd_populate_kernel(&init_mm, pmdp, ptep);
+       }
+
+       off = phys - virt;
+       for (sz_left = size;
+            sz_left >= PAGE_SIZE;
+            sz_left -= PAGE_SIZE, virt += PAGE_SIZE) {
+               ptep = pte_offset_kernel(pmdp, virt);
+               set_pte(ptep, __pte((virt + off) | prot_pte));
+       }
+       if (sz_left)
+               BUG();
+
+       return 0;
+}
+
+static void exmap_clear_armmmu(unsigned long virt, unsigned long size)
+{
+       unsigned long sz_left;
+       pmd_t *pmdp;
+       pte_t *ptep;
+
+       printk(KERN_DEBUG
+              "omapdsp: unmapping in ARM MMU, v=0x%08lx, sz=0x%lx\n",
+              virt, size);
+
+       for (sz_left = size;
+            sz_left >= PAGE_SIZE;
+            sz_left -= PAGE_SIZE, virt += PAGE_SIZE) {
+               pmdp = pmd_offset(pgd_offset_k(virt), virt);
+               ptep = pte_offset_kernel(pmdp, virt);
+               pte_clear(&init_mm, virt, ptep);
+       }
+       if (sz_left)
+               BUG();
+}
+
+static int exmap_valid(void *vadr, size_t len)
+{
+       /* exmap_sem should be held before calling this function */
+       int i;
+
+start:
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               void *mapadr;
+               unsigned long mapsize;
+               struct exmap_tbl *ent = &exmap_tbl[i];
+
+               if (!ent->valid)
+                       continue;
+               mapadr = (void *)ent->vadr;
+               mapsize = 1 << (ent->order + PAGE_SHIFT);
+               if ((vadr >= mapadr) && (vadr < mapadr + mapsize)) {
+                       if (vadr + len <= mapadr + mapsize) {
+                               /* this map covers whole address. */
+                               return 1;
+                       } else {
+                               /*
+                                * this map covers partially.
+                                * check rest portion.
+                                */
+                               len -= mapadr + mapsize - vadr;
+                               vadr = mapadr + mapsize;
+                               goto start;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len)
+{
+       void *ds = (void *)daram_base;
+       void *de = (void *)daram_base + daram_size;
+       void *ss = (void *)saram_base;
+       void *se = (void *)saram_base + saram_size;
+       int ret;
+
+       if ((vadr >= ds) && (vadr < de)) {
+               if (vadr + len > de)
+                       return MEM_TYPE_CROSSING;
+               else
+                       return MEM_TYPE_DARAM;
+       } else if ((vadr >= ss) && (vadr < se)) {
+               if (vadr + len > se)
+                       return MEM_TYPE_CROSSING;
+               else
+                       return MEM_TYPE_SARAM;
+       } else {
+               down_read(&exmap_sem);
+               if (exmap_valid(vadr, len))
+                       ret = MEM_TYPE_EXTERN;
+               else
+                       ret = MEM_TYPE_NONE;
+               up_read(&exmap_sem);
+               return ret;
+       }
+}
+
+int dsp_address_validate(void *p, size_t len, char *fmt, ...)
+{
+       if (dsp_mem_type(p, len) <= 0) {
+               if (fmt != NULL) {
+                       char s[64];
+                       va_list args;
+
+                       va_start(args, fmt);
+                       vsprintf(s, fmt, args);
+                       va_end(args);
+                       printk(KERN_ERR
+                              "omapdsp: %s address(0x%p) and size(0x%x) is "
+                              "not valid!\n"
+                              "         (crossing different type of memories, or \n"
+                              "          external memory space where no "
+                              "actual memory is mapped)\n",
+                              s, p, len);
+               }
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * exmap_use(), unuse(): 
+ * when the mapped area is exported to user space with mmap,
+ * the usecount is incremented.
+ * while the usecount > 0, that area can't be released.
+ */
+void exmap_use(void *vadr, size_t len)
+{
+       int i;
+
+       down_write(&exmap_sem);
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               void *mapadr;
+               unsigned long mapsize;
+               struct exmap_tbl *ent = &exmap_tbl[i];
+
+               if (!ent->valid)
+                       continue;
+               mapadr = (void *)ent->vadr;
+               mapsize = 1 << (ent->order + PAGE_SHIFT);
+               if ((vadr + len > mapadr) && (vadr < mapadr + mapsize)) {
+                       ent->usecount++;
+               }
+       }
+       up_write(&exmap_sem);
+}
+
+void exmap_unuse(void *vadr, size_t len)
+{
+       int i;
+
+       down_write(&exmap_sem);
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               void *mapadr;
+               unsigned long mapsize;
+               struct exmap_tbl *ent = &exmap_tbl[i];
+
+               if (!ent->valid)
+                       continue;
+               mapadr = (void *)ent->vadr;
+               mapsize = 1 << (ent->order + PAGE_SHIFT);
+               if ((vadr + len > mapadr) && (vadr < mapadr + mapsize)) {
+                       ent->usecount--;
+               }
+       }
+       up_write(&exmap_sem);
+}
+
+/*
+ * dsp_virt_to_phys()
+ * returns physical address, and sets len to valid length
+ */
+unsigned long dsp_virt_to_phys(void *vadr, size_t *len)
+{
+       int i;
+
+       if (is_dsp_internal_mem(vadr)) {
+               /* DSRAM or SARAM */
+               *len = dspmem_base + dspmem_size - (unsigned long)vadr;
+               return (unsigned long)vadr;
+       }
+
+       /* EXRAM */
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               void *mapadr;
+               unsigned long mapsize;
+               struct exmap_tbl *ent = &exmap_tbl[i];
+
+               if (!ent->valid)
+                       continue;
+               mapadr = (void *)ent->vadr;
+               mapsize = 1 << (ent->order + PAGE_SHIFT);
+               if ((vadr >= mapadr) && (vadr < mapadr + mapsize)) {
+                       *len = mapadr + mapsize - vadr;
+                       return __pa(ent->buf) + vadr - mapadr;
+               }
+       }
+
+       /* valid mapping not found */
+       return 0;
+}
+
+/*
+ * DSP MMU operations
+ */
+static __inline__ unsigned short get_cam_l_va_mask(unsigned short slst)
+{
+       switch (slst) {
+       case DSPMMU_CAM_L_SLST_1MB:
+               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
+                      DSPMMU_CAM_L_VA_TAG_L2_MASK_1MB;
+       case DSPMMU_CAM_L_SLST_64KB:
+               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
+                      DSPMMU_CAM_L_VA_TAG_L2_MASK_64KB;
+       case DSPMMU_CAM_L_SLST_4KB:
+               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
+                      DSPMMU_CAM_L_VA_TAG_L2_MASK_4KB;
+       case DSPMMU_CAM_L_SLST_1KB:
+               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
+                      DSPMMU_CAM_L_VA_TAG_L2_MASK_1KB;
+       }
+       return 0;
+}
+
+static __inline__ void get_tlb_lock(int *base, int *victim)
+{
+       unsigned short lock = omap_readw(DSPMMU_LOCK);
+       if (base != NULL)
+               *base = (lock & DSPMMU_LOCK_BASE_MASK)
+                       >> DSPMMU_LOCK_BASE_SHIFT;
+       if (victim != NULL)
+               *victim = (lock & DSPMMU_LOCK_VICTIM_MASK)
+                         >> DSPMMU_LOCK_VICTIM_SHIFT;
+}
+
+static __inline__ void set_tlb_lock(int base, int victim)
+{
+       omap_writew((base   << DSPMMU_LOCK_BASE_SHIFT) |
+                   (victim << DSPMMU_LOCK_VICTIM_SHIFT), DSPMMU_LOCK);
+}
+
+static __inline__ void __read_tlb(unsigned short lbase, unsigned short victim,
+                                 unsigned short *cam_h, unsigned short *cam_l,
+                                 unsigned short *ram_h, unsigned short *ram_l)
+{
+       /* set victim */
+       set_tlb_lock(lbase, victim);
+
+       /* read a TLB entry */
+       omap_writew(DSPMMU_LD_TLB_RD, DSPMMU_LD_TLB);
+
+       if (cam_h != NULL)
+               *cam_h = omap_readw(DSPMMU_READ_CAM_H);
+       if (cam_l != NULL)
+               *cam_l = omap_readw(DSPMMU_READ_CAM_L);
+       if (ram_h != NULL)
+               *ram_h = omap_readw(DSPMMU_READ_RAM_H);
+       if (ram_l != NULL)
+               *ram_l = omap_readw(DSPMMU_READ_RAM_L);
+}
+
+static __inline__ void __load_tlb(unsigned short cam_h, unsigned short cam_l,
+                                 unsigned short ram_h, unsigned short ram_l)
+{
+       omap_writew(cam_h, DSPMMU_CAM_H);
+       omap_writew(cam_l, DSPMMU_CAM_L);
+       omap_writew(ram_h, DSPMMU_RAM_H);
+       omap_writew(ram_l, DSPMMU_RAM_L);
+
+       /* flush the entry */
+       dsp_mmu_flush();
+
+       /* load a TLB entry */
+       omap_writew(DSPMMU_LD_TLB_LD, DSPMMU_LD_TLB);
+}
+
+static int dsp_mmu_load_tlb(unsigned long vadr, unsigned long padr,
+                           unsigned short slst, unsigned short prsvd,
+                           unsigned short ap)
+{
+       int lbase, victim;
+       unsigned short cam_l_va_mask;
+
+       clk_use(dsp_ck_handle);
+
+       get_tlb_lock(&lbase, NULL);
+       for (victim = 0; victim < lbase; victim++) {
+               unsigned short cam_l;
+
+               /* read a TLB entry */
+               __read_tlb(lbase, victim, NULL, &cam_l, NULL, NULL);
+               if (!(cam_l & DSPMMU_CAM_L_V))
+                       goto found_victim;
+       }
+       set_tlb_lock(lbase, victim);
+
+found_victim:
+       /* The last (31st) entry cannot be locked? */
+       if (victim == 31) {
+               printk(KERN_ERR "omapdsp: TLB is full.\n");
+               return -EBUSY;
+       }
+
+       cam_l_va_mask = get_cam_l_va_mask(slst);
+       if (vadr &
+           ~(DSPMMU_CAM_H_VA_TAG_H_MASK << 22 |
+             (unsigned long)cam_l_va_mask << 6)) {
+               printk(KERN_ERR
+                      "omapdsp: mapping vadr (0x%06lx) is not "
+                      "aligned boundary\n", vadr);
+               return -EINVAL;
+       }
+
+       __load_tlb(vadr >> 22, (vadr >> 6 & cam_l_va_mask) | prsvd | slst,
+                  padr >> 16, (padr & DSPMMU_RAM_L_RAM_LSB_MASK) | ap);
+
+       /* update lock base */
+       if (victim == lbase)
+               lbase++;
+       set_tlb_lock(lbase, lbase);
+
+       clk_unuse(dsp_ck_handle);
+       return 0;
+}
+
+static int dsp_mmu_clear_tlb(unsigned long vadr)
+{
+       int lbase;
+       int i;
+       int max_valid = 0;
+
+       clk_use(dsp_ck_handle);
+
+       get_tlb_lock(&lbase, NULL);
+       for (i = 0; i < lbase; i++) {
+               unsigned short cam_h, cam_l;
+               unsigned short cam_l_va_mask, cam_vld, slst;
+               unsigned long cam_va;
+
+               /* read a TLB entry */
+               __read_tlb(lbase, i, &cam_h, &cam_l, NULL, NULL);
+
+               cam_vld = cam_l & DSPMMU_CAM_L_V;
+               if (!cam_vld)
+                       continue;
+
+               slst = cam_l & DSPMMU_CAM_L_SLST_MASK;
+               cam_l_va_mask = get_cam_l_va_mask(slst);
+               cam_va = (unsigned long)(cam_h & DSPMMU_CAM_H_VA_TAG_H_MASK) << 22 |
+                        (unsigned long)(cam_l & cam_l_va_mask) << 6;
+
+               if (cam_va == vadr)
+                       /* flush the entry */
+                       dsp_mmu_flush();
+               else
+                       max_valid = i;
+       }
+
+       /* set new lock base */
+       set_tlb_lock(max_valid+1, max_valid+1);
+
+       clk_unuse(dsp_ck_handle);
+       return 0;
+}
+
+static void dsp_mmu_gflush(void)
+{
+       clk_use(dsp_ck_handle);
+
+       __dsp_mmu_gflush();
+       set_tlb_lock(1, 1);
+
+       clk_unuse(dsp_ck_handle);
+}
+
+/*
+ * dsp_exmap()
+ *
+ * OMAP_DSP_MEM_IOCTL_EXMAP ioctl calls this function with padr=0.
+ * In this case, the buffer for DSP is allocated in this routine,
+ * then it is mapped.
+ * On the other hand, for example - frame buffer sharing, calls
+ * this function with padr set. It means some known address space
+ * pointed with padr is going to be shared with DSP.
+ */
+static int dsp_exmap(unsigned long dspadr, unsigned long padr,
+                    unsigned long size, enum exmap_type type)
+{
+       unsigned short slst;
+       void *buf;
+       unsigned int order = 0;
+       unsigned long unit;
+       unsigned int cntnu = 0;
+       unsigned long _dspadr = dspadr;
+       unsigned long _padr = padr;
+       void *_vadr = dspbyte_to_virt(dspadr);
+       unsigned long _size = size;
+       struct exmap_tbl *exmap_ent;
+       int status;
+       int i;
+
+#define MINIMUM_PAGESZ SZ_4KB
+       /*
+        * alignment check
+        */
+       if (!is_aligned(size, MINIMUM_PAGESZ)) {
+               printk(KERN_ERR
+                      "omapdsp: size(0x%lx) is not multiple of 4KB.\n", size);
+               return -EINVAL;
+       }
+       if (!is_aligned(dspadr, MINIMUM_PAGESZ)) {
+               printk(KERN_ERR
+                      "omapdsp: DSP address(0x%lx) is not aligned.\n", dspadr);
+               return -EINVAL;
+       }
+       if (!is_aligned(padr, MINIMUM_PAGESZ)) {
+               printk(KERN_ERR
+                      "omapdsp: physical address(0x%lx) is not aligned.\n",
+                      padr);
+               return -EINVAL;
+       }
+
+       /* address validity check */
+       if ((dspadr < dspmem_size) ||
+           (dspadr >= DSPSPACE_SIZE) ||
+           ((dspadr + size > DSP_INIT_PAGE) &&
+            (dspadr < DSP_INIT_PAGE + PAGE_SIZE))) {
+               printk(KERN_ERR
+                      "omapdsp: illegal address/size for dsp_exmap().\n");
+               return -EINVAL;
+       }
+
+       down_write(&exmap_sem);
+
+       /* overlap check */
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               unsigned long mapsize;
+               struct exmap_tbl *tmp_ent = &exmap_tbl[i];
+
+               if (!tmp_ent->valid)
+                       continue;
+               mapsize = 1 << (tmp_ent->order + PAGE_SHIFT);
+               if ((_vadr + size > tmp_ent->vadr) &&
+                   (_vadr < tmp_ent->vadr + mapsize)) {
+                       printk(KERN_ERR "omapdsp: exmap page overlap!\n");
+                       up_write(&exmap_sem);
+                       return -EINVAL;
+               }
+       }
+
+start:
+       buf = NULL;
+       /* Are there any free TLB lines?  */
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               if (!exmap_tbl[i].valid)
+                       goto found_free;
+       }
+       printk(KERN_ERR "omapdsp: DSP TLB is full.\n");
+       status = -EBUSY;
+       goto fail;
+
+found_free:
+       exmap_ent = &exmap_tbl[i];
+
+       if ((_size >= SZ_1MB) &&
+           (is_aligned(_padr, SZ_1MB) || (padr == 0)) &&
+           is_aligned(_dspadr, SZ_1MB)) {
+               unit = SZ_1MB;
+               slst = DSPMMU_CAM_L_SLST_1MB;
+               order = ORDER_1MB;
+       } else if ((_size >= SZ_64KB) &&
+                  (is_aligned(_padr, SZ_64KB) || (padr == 0)) &&
+                  is_aligned(_dspadr, SZ_64KB)) {
+               unit = SZ_64KB;
+               slst = DSPMMU_CAM_L_SLST_64KB;
+               order = ORDER_64KB;
+       } else /* if (_size >= SZ_4KB) */ {
+               unit = SZ_4KB;
+               slst = DSPMMU_CAM_L_SLST_4KB;
+               order = ORDER_4KB;
+       }
+#if 0  /* 1KB is not enabled */
+       else if (_size >= SZ_1KB) {
+               unit = SZ_1KB;
+               slst = DSPMMU_CAM_L_SLST_1KB;
+               order = XXX;
+       }
+#endif
+
+       /* buffer allocation */
+       if (type == EXMAP_TYPE_MEM) {
+               struct page *page, *ps, *pe;
+
+               buf = (void *)dsp_mem_get_dma_pages(order);
+               if (buf == NULL) {
+                       status = -ENOMEM;
+                       goto fail;
+               }
+               /* mark the pages as reserved; this is needed for mmap */
+               ps = virt_to_page(buf);
+               pe = virt_to_page(buf + unit);
+               for (page = ps; page < pe; page++) {
+                       SetPageReserved(page);
+               }
+               _padr = __pa(buf);
+       }
+
+       /*
+        * mapping for ARM MMU:
+        * we should not access to the allocated memory through 'buf'
+        * since this area should not be cashed.
+        */
+       status = exmap_set_armmmu((unsigned long)_vadr, _padr, unit);
+       if (status < 0)
+               goto fail;
+
+       /* loading DSP TLB entry */
+       status = dsp_mmu_load_tlb(_dspadr, _padr, slst, 0, DSPMMU_RAM_L_AP_FA);
+       if (status < 0) {
+               exmap_clear_armmmu((unsigned long)_vadr, unit);
+               goto fail;
+       }
+
+       exmap_ent->buf      = buf;
+       exmap_ent->vadr     = _vadr;
+       exmap_ent->order    = order;
+       exmap_ent->valid    = 1;
+       exmap_ent->cntnu    = cntnu;
+       exmap_ent->type     = type;
+       exmap_ent->usecount = 0;
+
+       if ((_size -= unit) == 0) {     /* normal completion */
+               up_write(&exmap_sem);
+               return size;
+       }
+
+       _dspadr += unit;
+       _vadr   += unit;
+       _padr = padr ? _padr + unit : 0;
+       cntnu = 1;
+       goto start;
+
+fail:
+       up_write(&exmap_sem);
+       if (buf)
+               dsp_mem_free_pages((unsigned long)buf, order);
+       dsp_exunmap(dspadr);
+       return status;
+}
+
+static unsigned long unmap_free_arm(struct exmap_tbl *ent)
+{
+       unsigned long size;
+
+       /* clearing ARM MMU */
+       size = 1 << (ent->order + PAGE_SHIFT);
+       exmap_clear_armmmu((unsigned long)ent->vadr, size);
+
+       /* freeing allocated memory */
+       if (ent->type == EXMAP_TYPE_MEM) {
+               dsp_mem_free_pages((unsigned long)ent->buf, ent->order);
+               printk(KERN_DEBUG
+                      "omapdsp: freeing 0x%lx bytes @ adr 0x%8p\n",
+                      size, ent->buf);
+       }
+
+       return size;
+}
+
+static int dsp_exunmap(unsigned long dspadr)
+{
+       void *vadr;
+       unsigned long size;
+       int total = 0;
+       struct exmap_tbl *ent;
+       int idx;
+
+       vadr = dspbyte_to_virt(dspadr);
+       down_write(&exmap_sem);
+       for (idx = 0; idx < DSPMMU_TLB_LINES; idx++) {
+               ent = &exmap_tbl[idx];
+               if (!ent->valid)
+                       continue;
+               if (ent->vadr == vadr)
+                       goto found_map;
+       }
+       up_write(&exmap_sem);
+       printk(KERN_WARNING
+              "omapdsp: address %06lx not found in exmap_tbl.\n", dspadr);
+       return -EINVAL;
+
+found_map:
+       if (ent->usecount > 0) {
+               printk(KERN_ERR
+                      "omapdsp: exmap reference count is not 0.\n"
+                      "   idx=%d, vadr=%p, order=%d, usecount=%d\n",
+                      idx, ent->vadr, ent->order, ent->usecount);
+               up_write(&exmap_sem);
+               return -EINVAL;
+       }
+       /* clearing DSP TLB entry */
+       dsp_mmu_clear_tlb(dspadr);
+
+       /* clear ARM MMU and free buffer */
+       size = unmap_free_arm(ent);
+       ent->valid = 0;
+       total += size;
+
+       /* we don't free PTEs */
+
+       /* flush TLB */
+       flush_tlb_kernel_range((unsigned long)vadr, (unsigned long)vadr + size);
+
+       /* check if next mapping is in same group */
+       if (++idx == DSPMMU_TLB_LINES)
+               goto up_out;    /* normal completion */
+       ent = &exmap_tbl[idx];
+       if (!ent->valid || !ent->cntnu)
+               goto up_out;    /* normal completion */
+
+       dspadr += size;
+       vadr   += size;
+       if (ent->vadr == vadr)
+               goto found_map; /* continue */
+
+       printk(KERN_ERR
+              "omapdsp: illegal exmap_tbl grouping!\n"
+              "expected vadr = %p, exmap_tbl[%d].vadr = %p\n",
+              vadr, idx, ent->vadr);
+       up_write(&exmap_sem);
+       return -EINVAL;
+
+up_out:
+       up_write(&exmap_sem);
+       return total;
+}
+
+static void exmap_flush(void)
+{
+       struct exmap_tbl *ent;
+       int i;
+
+       down_write(&exmap_sem);
+
+       /* clearing DSP TLB entry */
+       dsp_mmu_gflush();
+
+       /* exmap_tbl[0] should be preserved */
+       for (i = 1; i < DSPMMU_TLB_LINES; i++) {
+               ent = &exmap_tbl[i];
+               if (ent->valid) {
+                       unmap_free_arm(ent);
+                       ent->valid = 0;
+               }
+       }
+
+       /* flush TLB */
+       flush_tlb_kernel_range(dspmem_base + dspmem_size,
+                              dspmem_base + DSPSPACE_SIZE);
+       up_write(&exmap_sem);
+}
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+#ifndef CONFIG_FB
+#error You configured OMAP_DSP_FBEXPORT, but FB was not configured!
+#endif /* CONFIG_FB */
+
+static int dsp_fbexport(unsigned long *dspadr)
+{
+       unsigned long dspadr_actual;
+       unsigned long padr_sys, padr, fbsz_sys, fbsz;
+       int cnt;
+
+       printk(KERN_DEBUG "omapdsp: frame buffer export\n");
+
+       if (num_registered_fb == 0) {
+               printk(KERN_INFO "omapdsp: frame buffer not registered.\n");
+               return -EINVAL;
+       }
+       if (num_registered_fb != 1) {
+               printk(KERN_INFO
+                      "omapdsp: %d frame buffers found. we use first one.\n",
+                      num_registered_fb);
+       }
+       padr_sys = registered_fb[0]->fix.smem_start;
+       fbsz_sys = registered_fb[0]->fix.smem_len;
+       if (fbsz_sys == 0) {
+               printk(KERN_ERR
+                      "omapdsp: framebuffer doesn't seem to be configured "
+                      "correctly! (size=0)\n");
+               return -EINVAL;
+       }
+
+       /*
+        * align padr and fbsz to 4kB boundary
+        * (should be noted to the user afterwards!)
+        */
+       padr = padr_sys & ~(SZ_4KB-1);
+       fbsz = (fbsz_sys + padr_sys - padr + SZ_4KB-1) & ~(SZ_4KB-1);
+
+       /* line up dspadr offset with padr */
+       dspadr_actual =
+               (fbsz > SZ_1MB) ?  lineup_offset(*dspadr, padr, SZ_1MB-1) :
+               (fbsz > SZ_64KB) ? lineup_offset(*dspadr, padr, SZ_64KB-1) :
+               /* (fbsz > SZ_4KB) ? */ *dspadr;
+       if (dspadr_actual != *dspadr)
+               printk(KERN_DEBUG
+                      "omapdsp: actual dspadr for FBEXPORT = %08lx\n",
+                      dspadr_actual);
+       *dspadr = dspadr_actual;
+
+       cnt = dsp_exmap(dspadr_actual, padr, fbsz, EXMAP_TYPE_FB);
+       if (cnt < 0) {
+               printk(KERN_ERR "omapdsp: exmap failure.\n");
+               return cnt;
+       }
+
+       if ((padr != padr_sys) || (fbsz != fbsz_sys)) {
+               printk(KERN_WARNING
+"  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+"  !!  screen base address or size is not aligned in 4kB:           !!\n"
+"  !!    actual screen  adr = %08lx, size = %08lx             !!\n"
+"  !!    exporting      adr = %08lx, size = %08lx             !!\n"
+"  !!  Make sure that the framebuffer is allocated with 4kB-order!  !!\n"
+"  !!  Otherwise DSP can corrupt the kernel memory.                 !!\n"
+"  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
+                      padr_sys, fbsz_sys, padr, fbsz);
+       }
+
+       /* increase the DMA priority */
+       set_emiff_dma_prio(15);
+
+       return cnt;
+}
+
+#else /* CONFIG_OMAP_DSP_FBEXPORT */
+
+static int dsp_fbexport(unsigned long *dspadr)
+{
+       printk(KERN_ERR "omapdsp: FBEXPORT function is not enabled.\n");
+       return -EINVAL;
+}
+
+#endif /* CONFIG_OMAP_DSP_FBEXPORT */
+
+static int dsp_mmu_itack(void)
+{
+       unsigned long dspadr;
+
+       printk(KERN_INFO "omapdsp: sending DSP MMU interrupt ack.\n");
+       if (!dsp_err_mmu_isset()) {
+               printk(KERN_ERR "omapdsp: DSP MMU error has not been set.\n");
+               return -EINVAL;
+       }
+       dspadr = dsp_fault_adr & ~(SZ_4K-1);
+       dsp_exmap(dspadr, 0, SZ_4K, EXMAP_TYPE_MEM);    /* FIXME: reserve TLB entry for this */
+       printk(KERN_INFO "omapdsp: falling into recovery runlevel...\n");
+       dsp_runlevel(OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY);
+       __dsp_mmu_itack();
+       udelay(100);
+       dsp_exunmap(dspadr);
+       dsp_err_mmu_clear();
+       return 0;
+}
+
+static void dsp_mmu_init(void)
+{
+       unsigned long phys;
+       void *virt;
+
+       clk_use(dsp_ck_handle);
+       down_write(&exmap_sem);
+
+       dsp_mmu_disable();      /* clear all */
+       udelay(100);
+       dsp_mmu_enable();
+
+       /* mapping for ARM MMU */
+       phys = __pa(dspvect_page);
+       virt = dspbyte_to_virt(DSP_INIT_PAGE);  /* 0xe0fff000 */
+       exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
+       exmap_tbl[0].buf      = dspvect_page;
+       exmap_tbl[0].vadr     = virt;
+       exmap_tbl[0].usecount = 0;
+       exmap_tbl[0].order    = 0;
+       exmap_tbl[0].valid    = 1;
+       exmap_tbl[0].cntnu    = 0;
+
+       /* DSP TLB initialization */
+       set_tlb_lock(0, 0);
+       /* preserved, full access */
+       dsp_mmu_load_tlb(DSP_INIT_PAGE, phys, DSPMMU_CAM_L_SLST_4KB,
+                        DSPMMU_CAM_L_P, DSPMMU_RAM_L_AP_FA);
+       up_write(&exmap_sem);
+       clk_unuse(dsp_ck_handle);
+}
+
+static void dsp_mmu_shutdown(void)
+{
+       exmap_flush();
+       dsp_mmu_disable();      /* clear all */
+}
+
+/*
+ * intmem_enable() / disable():
+ * if the address is in DSP internal memories,
+ * we send PM mailbox commands so that DSP DMA domain won't go in idle
+ * when ARM is accessing to those memories.
+ */
+static int intmem_enable(void)
+{
+       int ret = 0;
+
+       if (dsp_is_ready())
+               ret = dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
+                                DSPREG_ICR_DMA_IDLE_DOMAIN);
+
+       return ret;
+}
+
+static void intmem_disable(void) {
+       if (dsp_is_ready())
+               dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_DISABLE,
+                          DSPREG_ICR_DMA_IDLE_DOMAIN);
+}
+
+/*
+ * dsp_mem_enable() / disable()
+ */
+int intmem_usecount;
+
+int dsp_mem_enable(void *adr)
+{
+       int ret = 0;
+
+       if (is_dsp_internal_mem(adr)) {
+               if (intmem_usecount++ == 0)
+                       ret = omap_dsp_request_mem();
+       } else
+               down_read(&exmap_sem);
+
+       return ret;
+}
+
+void dsp_mem_disable(void *adr)
+{
+       if (is_dsp_internal_mem(adr)) {
+               if (--intmem_usecount == 0)
+                       omap_dsp_release_mem();
+       } else
+               up_read(&exmap_sem);
+}
+
+/* for safety */
+void dsp_mem_usecount_clear(void)
+{
+       if (intmem_usecount != 0) {
+               printk(KERN_WARNING
+                      "omapdsp: unbalanced memory request/release detected.\n"
+                      "         intmem_usecount is not zero at where "
+                      "it should be! ... fixed to be zero.\n");
+               intmem_usecount = 0;
+               omap_dsp_release_mem();
+       }
+}
+
+/*
+ * dsp_mem file operations
+ */
+static loff_t dsp_mem_lseek(struct file *file, loff_t offset, int orig)
+{
+       loff_t ret;
+
+       down(&file->f_dentry->d_inode->i_sem);
+       switch (orig) {
+       case 0:
+               file->f_pos = offset;
+               ret = file->f_pos;
+               break;
+       case 1:
+               file->f_pos += offset;
+               ret = file->f_pos;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       up(&file->f_dentry->d_inode->i_sem);
+       return ret;
+}
+
+static ssize_t intmem_read(struct file *file, char *buf, size_t count,
+                          loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       void *vadr = dspbyte_to_virt(p);
+       ssize_t size = dspmem_size;
+       ssize_t read;
+
+       if (p >= size)
+               return 0;
+       clk_use(api_ck_handle);
+       read = count;
+       if (count > size - p)
+               read = size - p;
+       if (copy_to_user(buf, vadr, read)) {
+               read = -EFAULT;
+               goto out;
+       }
+       *ppos += read;
+out:
+       clk_unuse(api_ck_handle);
+       return read;
+}
+
+static ssize_t exmem_read(struct file *file, char *buf, size_t count,
+                         loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       void *vadr = dspbyte_to_virt(p);
+
+       if (!exmap_valid(vadr, count)) {
+               printk(KERN_ERR
+                      "omapdsp: DSP address %08lx / size %08x "
+                      "is not valid!\n", p, count);
+               return -EFAULT;
+       }
+       if (count > DSPSPACE_SIZE - p)
+               count = DSPSPACE_SIZE - p;
+       if (copy_to_user(buf, vadr, count))
+               return -EFAULT;
+       *ppos += count;
+
+       return count;
+}
+
+static ssize_t dsp_mem_read(struct file *file, char *buf, size_t count,
+                           loff_t *ppos)
+{
+       int ret;
+       void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
+
+       if (dsp_mem_enable(vadr) < 0)
+               return -EBUSY;
+       if (is_dspbyte_internal_mem(*ppos))
+               ret = intmem_read(file, buf, count, ppos);
+       else
+               ret = exmem_read(file, buf, count, ppos);
+       dsp_mem_disable(vadr);
+
+       return ret;
+}
+
+static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
+                           loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       void *vadr = dspbyte_to_virt(p);
+       ssize_t size = dspmem_size;
+       ssize_t written;
+
+       if (p >= size)
+               return 0;
+       clk_use(api_ck_handle);
+       written = count;
+       if (count > size - p)
+               written = size - p;
+       if (copy_from_user(vadr, buf, written)) {
+               written = -EFAULT;
+               goto out;
+       }
+       *ppos += written;
+out:
+       clk_unuse(api_ck_handle);
+       return written;
+}
+
+static ssize_t exmem_write(struct file *file, const char *buf, size_t count,
+                          loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       void *vadr = dspbyte_to_virt(p);
+
+       if (!exmap_valid(vadr, count)) {
+               printk(KERN_ERR
+                      "omapdsp: DSP address %08lx / size %08x "
+                      "is not valid!\n", p, count);
+               return -EFAULT;
+       }
+       if (count > DSPSPACE_SIZE - p)
+               count = DSPSPACE_SIZE - p;
+       if (copy_from_user(vadr, buf, count))
+               return -EFAULT;
+       *ppos += count;
+
+       return count;
+}
+
+static ssize_t dsp_mem_write(struct file *file, const char *buf, size_t count,
+                            loff_t *ppos)
+{
+       int ret;
+       void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
+
+       if (dsp_mem_enable(vadr) < 0)
+               return -EBUSY;
+       if (is_dspbyte_internal_mem(*ppos))
+               ret = intmem_write(file, buf, count, ppos);
+       else
+               ret = exmem_write(file, buf, count, ppos);
+       dsp_mem_disable(vadr);
+
+       return ret;
+}
+
+static int dsp_mem_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case OMAP_DSP_MEM_IOCTL_MMUINIT:
+               dsp_mmu_init();
+               return 0;
+
+       case OMAP_DSP_MEM_IOCTL_EXMAP:
+               {
+                       struct omap_dsp_mapinfo mapinfo;
+                       if (copy_from_user(&mapinfo, (void *)arg,
+                                          sizeof(mapinfo)))
+                               return -EFAULT;
+                       return dsp_exmap(mapinfo.dspadr, 0, mapinfo.size,
+                                        EXMAP_TYPE_MEM);
+               }
+
+       case OMAP_DSP_MEM_IOCTL_EXUNMAP:
+               return dsp_exunmap((unsigned long)arg);
+
+       case OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH:
+               exmap_flush();
+               return 0;
+
+       case OMAP_DSP_MEM_IOCTL_FBEXPORT:
+               {
+                       unsigned long dspadr;
+                       int ret;
+                       if (copy_from_user(&dspadr, (void *)arg, sizeof(long)))
+                               return -EFAULT;
+                       ret = dsp_fbexport(&dspadr);
+                       if (copy_to_user((void *)arg, &dspadr, sizeof(long)))
+                               return -EFAULT;
+                       return ret;
+               }
+
+       case OMAP_DSP_MEM_IOCTL_MMUITACK:
+               return dsp_mmu_itack();
+
+       case OMAP_DSP_MEM_IOCTL_KMEM_RESERVE:
+               {
+                       unsigned long size;
+                       if (copy_from_user(&size, (void *)arg, sizeof(long)))
+                               return -EFAULT;
+                       return dsp_kmem_reserve(size);
+               }
+
+       case OMAP_DSP_MEM_IOCTL_KMEM_RELEASE:
+               dsp_kmem_release();
+               return 0;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
+static int dsp_mem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       /*
+        * FIXME
+        */
+       return -ENOSYS;
+}
+
+static int dsp_mem_open(struct inode *inode, struct file *file)
+{
+       if (!capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       return 0;
+}
+
+static int dsp_mem_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+/*
+ * sysfs files
+ */
+static ssize_t mmu_show(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       int len;
+       int lbase, victim;
+       int i;
+
+       clk_use(dsp_ck_handle);
+       down_read(&exmap_sem);
+
+       get_tlb_lock(&lbase, &victim);
+
+       len = sprintf(buf, "p: preserved,  v: valid\n"
+                          "ety       cam_va     ram_pa   sz ap\n");
+                       /* 00: p v 0x300000 0x10171800 64KB FA */
+       for (i = 0; i < 32; i++) {
+               unsigned short cam_h, cam_l, ram_h, ram_l;
+               unsigned short cam_l_va_mask, prsvd, cam_vld, slst;
+               unsigned long cam_va;
+               unsigned short ram_l_ap;
+               unsigned long ram_pa;
+               char *pgsz_str, *ap_str;
+
+               /* read a TLB entry */
+               __read_tlb(lbase, i, &cam_h, &cam_l, &ram_h, &ram_l);
+
+               slst = cam_l & DSPMMU_CAM_L_SLST_MASK;
+               cam_l_va_mask = get_cam_l_va_mask(slst);
+               pgsz_str = (slst == DSPMMU_CAM_L_SLST_1MB) ? " 1MB":
+                          (slst == DSPMMU_CAM_L_SLST_64KB)? "64KB":
+                          (slst == DSPMMU_CAM_L_SLST_4KB) ? " 4KB":
+                                                            " 1KB";
+               prsvd    = cam_l & DSPMMU_CAM_L_P;
+               cam_vld  = cam_l & DSPMMU_CAM_L_V;
+               ram_l_ap = ram_l & DSPMMU_RAM_L_AP_MASK;
+               ap_str = (ram_l_ap == DSPMMU_RAM_L_AP_RO) ? "RO":
+                        (ram_l_ap == DSPMMU_RAM_L_AP_FA) ? "FA":
+                                                           "NA";
+               cam_va = (unsigned long)(cam_h & DSPMMU_CAM_H_VA_TAG_H_MASK) << 22 |
+                        (unsigned long)(cam_l & cam_l_va_mask) << 6;
+               ram_pa = (unsigned long)ram_h << 16 |
+                        (ram_l & DSPMMU_RAM_L_RAM_LSB_MASK);
+
+               if (i == lbase)
+                       len += sprintf(buf + len, "lock base = %d\n", lbase);
+               if (i == victim)
+                       len += sprintf(buf + len, "victim    = %d\n", victim);
+               /* 00: p v 0x300000 0x10171800 64KB FA */
+               len += sprintf(buf + len,
+                              "%02d: %c %c 0x%06lx 0x%08lx %s %s\n",
+                              i,
+                              prsvd   ? 'p' : ' ',
+                              cam_vld ? 'v' : ' ',
+                              cam_va, ram_pa, pgsz_str, ap_str);
+       }
+
+       /* restore victim entry */
+       set_tlb_lock(lbase, victim);
+
+       up_read(&exmap_sem);
+       clk_unuse(dsp_ck_handle);
+       return len;
+}
+
+static struct device_attribute dev_attr_mmu = __ATTR_RO(mmu);
+
+static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       int len;
+       int i;
+
+       down_read(&exmap_sem);
+       len = sprintf(buf, "v: valid,  c: cntnu\n"
+                          "ety           vadr        buf od uc\n");
+                        /* 00: v c 0xe0300000 0xc0171800  0 */
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               struct exmap_tbl *ent = &exmap_tbl[i];
+               /* 00: v c 0xe0300000 0xc0171800  0 */
+               len += sprintf(buf + len, "%02d: %c %c 0x%8p 0x%8p %2d %2d\n",
+                              i,
+                              ent->valid ? 'v' : ' ',
+                              ent->cntnu ? 'c' : ' ',
+                              ent->vadr, ent->buf, ent->order, ent->usecount);
+       }
+
+       up_read(&exmap_sem);
+       return len;
+}
+
+static struct device_attribute dev_attr_exmap = __ATTR_RO(exmap);
+
+static ssize_t kmem_pool_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       int count_1M, count_64K, total;
+
+       count_1M = kmem_pool_1M.count;
+       count_64K = kmem_pool_64K.count;
+       total = count_1M * SZ_1MB + count_64K * SZ_64KB;
+
+       return sprintf(buf, "0x%x %d %d\n", total, count_1M, count_64K);
+}
+
+static struct device_attribute dev_attr_kmem_pool = __ATTR_RO(kmem_pool);
+
+/*
+ * DSP MMU interrupt handler
+ */
+
+/*
+ * MMU fault mask:
+ * We ignore prefetch err.
+ */
+#define MMUFAULT_MASK \
+       (DSPMMU_FAULT_ST_PERM |\
+        DSPMMU_FAULT_ST_TLB_MISS |\
+        DSPMMU_FAULT_ST_TRANS)
+irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned short status;
+       unsigned short adh, adl;
+       unsigned short dp;
+
+       status = omap_readw(DSPMMU_FAULT_ST);
+       adh = omap_readw(DSPMMU_FAULT_AD_H);
+       adl = omap_readw(DSPMMU_FAULT_AD_L);
+       dp = adh & DSPMMU_FAULT_AD_H_DP;
+       dsp_fault_adr = MKLONG(adh & DSPMMU_FAULT_AD_H_ADR_MASK, adl);
+       /* if the fault is masked, nothing to do */
+       if ((status & MMUFAULT_MASK) == 0) {
+               printk(KERN_DEBUG "DSP MMU interrupt, but ignoring.\n");
+               /*
+                * note: in OMAP1710,
+                * when CACHE + DMA domain gets out of idle in DSP,
+                * MMU interrupt occurs but DSPMMU_FAULT_ST is not set.
+                * in this case, we just ignore the interrupt.
+                */
+               if (status) {
+                       printk(KERN_DEBUG "%s%s%s%s\n",
+                              (status & DSPMMU_FAULT_ST_PREF)?
+                                       "  (prefetch err)" : "",
+                              (status & DSPMMU_FAULT_ST_PERM)?
+                                       "  (permission fault)" : "",
+                              (status & DSPMMU_FAULT_ST_TLB_MISS)?
+                                       "  (TLB miss)" : "",
+                              (status & DSPMMU_FAULT_ST_TRANS) ?
+                                       "  (translation fault)": "");
+                       printk(KERN_DEBUG
+                              "fault address = %s: 0x%06lx\n",
+                              dp ? "DATA" : "PROGRAM",
+                              dsp_fault_adr);
+               }
+               return IRQ_HANDLED;
+       }
+
+       printk(KERN_INFO "DSP MMU interrupt!\n");
+       printk(KERN_INFO "%s%s%s%s\n",
+              (status & DSPMMU_FAULT_ST_PREF)?
+                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_PREF)?
+                               "  prefetch err":
+                               "  (prefetch err)":
+                               "",
+              (status & DSPMMU_FAULT_ST_PERM)?
+                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_PERM)?
+                               "  permission fault":
+                               "  (permission fault)":
+                               "",
+              (status & DSPMMU_FAULT_ST_TLB_MISS)?
+                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_TLB_MISS)?
+                               "  TLB miss":
+                               "  (TLB miss)":
+                               "",
+              (status & DSPMMU_FAULT_ST_TRANS)?
+                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_TRANS)?
+                               "  translation fault":
+                               "  (translation fault)":
+                               "");
+       printk(KERN_INFO "fault address = %s: 0x%06lx\n",
+              dp ? "DATA" : "PROGRAM",
+              dsp_fault_adr);
+
+       if (dsp_is_ready()) {
+               /*
+                * If we call dsp_exmap() here,
+                * "kernel BUG at slab.c" occurs.
+                */
+               /* FIXME */
+               dsp_err_mmu_set(dsp_fault_adr);
+       } else {
+               disable_irq(INT_DSP_MMU);
+               __dsp_mmu_itack();
+               printk(KERN_INFO "Resetting DSP...\n");
+               dsp_cpustat_request(CPUSTAT_RESET);
+               enable_irq(INT_DSP_MMU);
+               /*
+                * if we enable followings, semaphore lock should be avoided.
+                *
+               printk(KERN_INFO "Flushing DSP MMU...\n");
+               exmap_flush();
+               dsp_mmu_init();
+                */
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ *
+ */
+struct file_operations dsp_mem_fops = {
+       .owner   = THIS_MODULE,
+       .llseek  = dsp_mem_lseek,
+       .read    = dsp_mem_read,
+       .write   = dsp_mem_write,
+       .ioctl   = dsp_mem_ioctl,
+       .mmap    = dsp_mem_mmap,
+       .open    = dsp_mem_open,
+       .release = dsp_mem_release,
+};
+
+void dsp_mem_start(void)
+{
+       dsp_register_mem_cb(intmem_enable, intmem_disable);
+}
+
+void dsp_mem_stop(void)
+{
+       memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
+       dsp_unregister_mem_cb();
+}
+
+int __init dsp_mem_init(void)
+{
+       int i;
+
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               exmap_tbl[i].valid = 0;
+       }
+
+       dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0);
+       if (dspvect_page == NULL) {
+               printk(KERN_ERR
+                      "omapdsp: failed to allocate memory "
+                      "for dsp vector table\n");
+               return -ENOMEM;
+       }
+       dsp_mmu_init();
+       dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE);
+
+       device_create_file(&dsp_device.dev, &dev_attr_mmu);
+       device_create_file(&dsp_device.dev, &dev_attr_exmap);
+       device_create_file(&dsp_device.dev, &dev_attr_kmem_pool);
+
+       return 0;
+}
+
+void dsp_mem_exit(void)
+{
+       dsp_mmu_shutdown();
+       dsp_kmem_release();
+
+       if (dspvect_page != NULL) {
+               unsigned long virt;
+
+               down_read(&exmap_sem);
+
+               virt = (unsigned long)dspbyte_to_virt(DSP_INIT_PAGE);
+               flush_tlb_kernel_range(virt, virt + PAGE_SIZE);
+               free_page((unsigned long)dspvect_page);
+               dspvect_page = NULL;
+
+               up_read(&exmap_sem);
+       }
+
+       device_remove_file(&dsp_device.dev, &dev_attr_mmu);
+       device_remove_file(&dsp_device.dev, &dev_attr_exmap);
+       device_remove_file(&dsp_device.dev, &dev_attr_kmem_pool);
+}
diff --git a/arch/arm/plat-omap/dsp/error.c b/arch/arm/plat-omap/dsp/error.c
new file mode 100644 (file)
index 0000000..dd7d7c4
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/error.c
+ *
+ * OMAP DSP error detection I/F device driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/03/11:  DSP Gateway version 3.3
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/ioctls.h>
+#include <asm/arch/dsp.h>
+#include "dsp.h"
+
+static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
+static unsigned long errcode;
+static int errcnt;
+static unsigned short wdtval;  /* FIXME: read through ioctl */
+static unsigned long mmu_fadr; /* FIXME: read through ioctl */
+
+/*
+ * DSP error detection device file operations
+ */
+static ssize_t dsp_err_read(struct file *file, char *buf, size_t count,
+                           loff_t *ppos)
+{
+       unsigned long flags;
+       int status;
+
+       if (count < 4)
+               return 0;
+
+       if (errcnt == 0) {
+               long current_state;
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue(&err_wait_q, &wait);
+               current_state = current->state;
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (errcnt == 0)        /* last check */
+                       schedule();
+               set_current_state(current_state);
+               remove_wait_queue(&err_wait_q, &wait);
+               if (signal_pending(current))
+                       return -EINTR;
+       }
+
+       local_irq_save(flags);
+       status = copy_to_user(buf, &errcode, 4);
+       if (status) {
+               local_irq_restore(flags);
+               return -EFAULT;
+       }
+       errcnt = 0;
+       local_irq_restore(flags);
+
+       return 4;
+}
+
+static unsigned int dsp_err_poll(struct file *file, poll_table *wait)
+{
+       unsigned int mask = 0;
+
+       poll_wait(file, &err_wait_q, wait);
+       if (errcnt != 0)
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+
+struct file_operations dsp_err_fops = {
+       .owner = THIS_MODULE,
+       .poll  = dsp_err_poll,
+       .read  = dsp_err_read,
+};
+
+/*
+ * DSP MMU
+ */
+void dsp_err_mmu_set(unsigned long adr)
+{
+       disable_irq(INT_DSP_MMU);
+       errcode |= OMAP_DSP_ERRDT_MMU;
+       errcnt++;
+       mmu_fadr = adr;
+       wake_up_interruptible(&err_wait_q);
+}
+
+void dsp_err_mmu_clear(void)
+{
+       errcode &= ~OMAP_DSP_ERRDT_MMU;
+       enable_irq(INT_DSP_MMU);
+}
+
+int dsp_err_mmu_isset(void)
+{
+       return (errcode & OMAP_DSP_ERRDT_MMU) ? 1 : 0;
+}
+
+/*
+ * WDT
+ */
+void dsp_err_wdt_clear(void)
+{
+       errcode &= ~OMAP_DSP_ERRDT_WDT;
+}
+
+int dsp_err_wdt_isset(void)
+{
+       return (errcode & OMAP_DSP_ERRDT_WDT) ? 1 : 0;
+}
+
+/*
+ * functions called from mailbox1 interrupt routine
+ */
+static void mbx1_err_wdt(unsigned short data)
+{
+       errcode |= OMAP_DSP_ERRDT_WDT;
+       errcnt++;
+       wdtval = data;
+       wake_up_interruptible(&err_wait_q);
+}
+
+#ifdef OLD_BINARY_SUPPORT
+/* v3.3 obsolete */
+void mbx1_wdt(struct mbcmd *mb)
+{
+       mbx1_err_wdt(mb->data);
+}
+#endif
+
+extern void mbx1_err_ipbfull(void);
+extern void mbx1_err_fatal(unsigned char tid);
+
+void mbx1_err(struct mbcmd *mb)
+{
+       unsigned char eid = mb->cmd_l;
+       char *eidnm = subcmd_name(mb);
+       unsigned char tid;
+
+       if (eidnm) {
+               printk(KERN_WARNING
+                      "mbx: ERR from DSP (%s): 0x%04x\n", eidnm, mb->data);
+       } else {
+               printk(KERN_WARNING
+                      "mbx: ERR from DSP (unknown EID=%02x): %04x\n",
+                      eid, mb->data);
+       }
+
+       switch (eid) {
+       case OMAP_DSP_EID_IPBFULL:
+               mbx1_err_ipbfull();
+               break;
+
+       case OMAP_DSP_EID_FATAL:
+               tid = mb->data & 0x00ff;
+               mbx1_err_fatal(tid);
+               break;
+
+       case OMAP_DSP_EID_WDT:
+               mbx1_err_wdt(mb->data);
+               break;
+       }
+}
+
+/*
+ *
+ */
+void dsp_err_start(void)
+{
+       errcnt = 0;
+       if (dsp_err_wdt_isset())
+               dsp_err_wdt_clear();
+       if (dsp_err_mmu_isset())
+               dsp_err_mmu_clear();
+}
+
+void dsp_err_stop(void)
+{
+       wake_up_interruptible(&err_wait_q);
+}
diff --git a/arch/arm/plat-omap/dsp/fifo.h b/arch/arm/plat-omap/dsp/fifo.h
new file mode 100644 (file)
index 0000000..46fc33c
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/fifo.h
+ *
+ * FIFO buffer operators
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/02/24:  DSP Gateway version 3.3
+ */
+
+struct fifo_struct {
+       spinlock_t lock;
+       char *buf;
+       size_t sz;
+       size_t cnt;
+       unsigned int wp;
+};
+
+static inline int alloc_fifo(struct fifo_struct *fifo, size_t sz)
+{
+       if ((fifo->buf = kmalloc(sz, GFP_KERNEL)) == NULL) {
+               fifo->sz = 0;
+               return -ENOMEM;
+       }
+       fifo->sz = sz;
+       fifo->cnt = 0;
+       fifo->wp = 0;
+       return 0;
+}
+
+static inline int init_fifo(struct fifo_struct *fifo, size_t sz)
+{
+       spin_lock_init(&fifo->lock);
+       return alloc_fifo(fifo, sz);
+}
+
+static inline void free_fifo(struct fifo_struct *fifo)
+{
+       spin_lock(&fifo->lock);
+       if (fifo->buf == NULL)
+               return;
+
+       kfree(fifo->buf);
+       fifo->buf = NULL;
+       fifo->sz = 0;
+       spin_unlock(&fifo->lock);
+}
+
+static inline void flush_fifo(struct fifo_struct *fifo)
+{
+       spin_lock(&fifo->lock);
+       fifo->cnt = 0;
+       fifo->wp = 0;
+       spin_unlock(&fifo->lock);
+}
+
+#define fifo_empty(fifo)       ((fifo)->cnt == 0)
+
+static inline int realloc_fifo(struct fifo_struct *fifo, size_t sz)
+{
+       int ret = sz;
+
+       spin_lock(&fifo->lock);
+       if (!fifo_empty(fifo)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* free */
+       if (fifo->buf)
+               kfree(fifo->buf);
+
+       /* alloc */
+       if ((fifo->buf = kmalloc(sz, GFP_KERNEL)) == NULL) {
+               fifo->sz = 0;
+               ret = -ENOMEM;
+               goto out;
+       }
+       fifo->sz = sz;
+       fifo->cnt = 0;
+       fifo->wp = 0;
+
+out:
+       spin_unlock(&fifo->lock);
+       return ret;
+}
+
+static inline void write_word_to_fifo(struct fifo_struct *fifo,
+                                     unsigned short word)
+{
+       spin_lock(&fifo->lock);
+       *(unsigned short *)&fifo->buf[fifo->wp] = word;
+       if ((fifo->wp += 2) == fifo->sz)
+               fifo->wp = 0;
+       if ((fifo->cnt += 2) > fifo->sz)
+               fifo->cnt = fifo->sz;
+       spin_unlock(&fifo->lock);
+}
+
+/*
+ * (before)
+ *
+ * [*******----------*************]
+ *         ^wp
+ *  <---------------------------->  sz = 30
+ *  <----->          <----------->  cnt = 20
+ *
+ * (read: count=16)
+ *  <->              <----------->  count = 16
+ *                   <----------->  cnt1 = 13
+ *                   ^rp
+ *
+ * (after)
+ * [---****-----------------------]
+ *         ^wp
+ */
+static inline ssize_t copy_to_user_fm_fifo(char *dst, struct fifo_struct *fifo,
+                                          size_t count)
+{
+       int rp;
+       ssize_t ret;
+
+       /* fifo size can be zero */
+       if (fifo->sz == 0)
+               return 0;
+
+       spin_lock(&fifo->lock);
+       if (count > fifo->cnt)
+               count = fifo->cnt;
+
+       if ((rp = fifo->wp - fifo->cnt) >= 0) {
+               /* valid area is straight */
+               if (copy_to_user(dst, &fifo->buf[rp], count)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+       } else {
+               int cnt1 = -rp;
+               rp += fifo->sz;
+               if (cnt1 >= count) {
+                       /* requested area is straight */
+                       if (copy_to_user(dst, &fifo->buf[rp], count)) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+               } else {
+                       if (copy_to_user(dst, &fifo->buf[rp], cnt1)) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+                       if (copy_to_user(dst+cnt1, fifo->buf, count-cnt1)) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+               }
+       }
+       fifo->cnt -= count;
+       ret = count;
+
+out:
+       spin_unlock(&fifo->lock);
+       return ret;
+}
diff --git a/arch/arm/plat-omap/dsp/hardware_dsp.h b/arch/arm/plat-omap/dsp/hardware_dsp.h
new file mode 100644 (file)
index 0000000..1308e53
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/hardware_dsp.h
+ *
+ * Register bit definitions for DSP driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/05/30:  DSP Gateway version 3.3
+ */
+
+#ifndef __OMAP_DSP_HARDWARE_DSP_H
+#define __OMAP_DSP_HARDWARE_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP15XX
+#define OMAP1510_DARAM_BASE    0xe0000000
+#define OMAP1510_DARAM_SIZE    0x10000
+#define OMAP1510_SARAM_BASE    0xe0010000
+#define OMAP1510_SARAM_SIZE    0x18000
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+#define OMAP16XX_DARAM_BASE    0xe0000000
+#define OMAP16XX_DARAM_SIZE    0x10000
+#define OMAP16XX_SARAM_BASE    0xe0010000
+#define OMAP16XX_SARAM_SIZE    0x18000
+#endif
+
+/*
+ * MAJOR device number: !! allocated arbitrary !!
+ */
+#define OMAP_DSP_CTL_MAJOR             96
+#define OMAP_DSP_TASK_MAJOR            97
+
+/*
+ * Reset Control
+ */
+#define ARM_RSTCT1_SW_RST              0x0008
+#define ARM_RSTCT1_DSP_RST             0x0004
+#define ARM_RSTCT1_DSP_EN              0x0002
+#define ARM_RSTCT1_ARM_RST             0x0001
+
+/*
+ * MPUI
+ */
+#define MPUI_CTRL_WORDSWAP_MASK                0x00600000
+#define MPUI_CTRL_WORDSWAP_ALL         0x00000000
+#define MPUI_CTRL_WORDSWAP_NONAPI      0x00200000
+#define MPUI_CTRL_WORDSWAP_API         0x00400000
+#define MPUI_CTRL_WORDSWAP_NONE                0x00600000
+#define MPUI_CTRL_AP_MASK              0x001c0000
+#define MPUI_CTRL_AP_MDH               0x00000000
+#define MPUI_CTRL_AP_MHD               0x00040000
+#define MPUI_CTRL_AP_DMH               0x00080000
+#define MPUI_CTRL_AP_HMD               0x000c0000
+#define MPUI_CTRL_AP_DHM               0x00100000
+#define MPUI_CTRL_AP_HDM               0x00140000
+#define MPUI_CTRL_BYTESWAP_MASK                0x00030000
+#define MPUI_CTRL_BYTESWAP_NONE                0x00000000
+#define MPUI_CTRL_BYTESWAP_NONAPI      0x00010000
+#define MPUI_CTRL_BYTESWAP_ALL         0x00020000
+#define MPUI_CTRL_BYTESWAP_API         0x00030000
+#define MPUI_CTRL_TIMEOUT_MASK         0x0000ff00
+#define MPUI_CTRL_APIF_HNSTB_DIV_MASK  0x000000f0
+#define MPUI_CTRL_S_NABORT_GL          0x00000008
+#define MPUI_CTRL_S_NABORT_32BIT       0x00000004
+#define MPUI_CTRL_EN_TIMEOUT           0x00000002
+#define MPUI_CTRL_HF_MCUCLK            0x00000001
+#define MPUI_DSP_BOOT_CONFIG_DIRECT    0x00000000
+#define MPUI_DSP_BOOT_CONFIG_PSD_DIRECT        0x00000001
+#define MPUI_DSP_BOOT_CONFIG_IDLE      0x00000002
+#define MPUI_DSP_BOOT_CONFIG_DL16      0x00000003
+#define MPUI_DSP_BOOT_CONFIG_DL32      0x00000004
+#define MPUI_DSP_BOOT_CONFIG_MPUI      0x00000005
+#define MPUI_DSP_BOOT_CONFIG_INTERNAL  0x00000006
+
+/*
+ * DSP boot mode
+ *   direct:        0xffff00
+ *   pseudo direct: 0x080000
+ *   MPUI:          branch 0x010000
+ *   internel:      branch 0x024000
+ */
+#define DSP_BOOT_ADR_DIRECT            0xffff00
+#define DSP_BOOT_ADR_PSD_DIRECT                0x080000
+#define DSP_BOOT_ADR_MPUI              0x010000
+#define DSP_BOOT_ADR_INTERNAL          0x024000
+
+/*
+ * TC
+ */
+#define TC_ENDIANISM_SWAP              0x00000002
+#define TC_ENDIANISM_SWAP_WORD         0x00000002
+#define TC_ENDIANISM_SWAP_BYTE         0x00000000
+#define TC_ENDIANISM_EN                        0x00000001
+
+/*
+ * DSP MMU
+ */
+#define DSPMMU_BASE                    (0xfffed200)
+#define DSPMMU_PREFETCH                        (DSPMMU_BASE + 0x00)
+#define DSPMMU_WALKING_ST              (DSPMMU_BASE + 0x04)
+#define DSPMMU_CNTL                    (DSPMMU_BASE + 0x08)
+#define DSPMMU_FAULT_AD_H              (DSPMMU_BASE + 0x0c)
+#define DSPMMU_FAULT_AD_L              (DSPMMU_BASE + 0x10)
+#define DSPMMU_FAULT_ST                        (DSPMMU_BASE + 0x14)
+#define DSPMMU_IT_ACK                  (DSPMMU_BASE + 0x18)
+#define DSPMMU_TTB_H                   (DSPMMU_BASE + 0x1c)
+#define DSPMMU_TTB_L                   (DSPMMU_BASE + 0x20)
+#define DSPMMU_LOCK                    (DSPMMU_BASE + 0x24)
+#define DSPMMU_LD_TLB                  (DSPMMU_BASE + 0x28)
+#define DSPMMU_CAM_H                   (DSPMMU_BASE + 0x2c)
+#define DSPMMU_CAM_L                   (DSPMMU_BASE + 0x30)
+#define DSPMMU_RAM_H                   (DSPMMU_BASE + 0x34)
+#define DSPMMU_RAM_L                   (DSPMMU_BASE + 0x38)
+#define DSPMMU_GFLUSH                  (DSPMMU_BASE + 0x3c)
+#define DSPMMU_FLUSH_ENTRY             (DSPMMU_BASE + 0x40)
+#define DSPMMU_READ_CAM_H              (DSPMMU_BASE + 0x44)
+#define DSPMMU_READ_CAM_L              (DSPMMU_BASE + 0x48)
+#define DSPMMU_READ_RAM_H              (DSPMMU_BASE + 0x4c)
+#define DSPMMU_READ_RAM_L              (DSPMMU_BASE + 0x50)
+
+#define DSPMMU_CNTL_BURST_16MNGT_EN    0x0020
+#define DSPMMU_CNTL_WTL_EN             0x0004
+#define DSPMMU_CNTL_MMU_EN             0x0002
+#define DSPMMU_CNTL_RESET_SW           0x0001
+
+#define DSPMMU_FAULT_AD_H_DP           0x0100
+#define DSPMMU_FAULT_AD_H_ADR_MASK     0x00ff
+
+#define DSPMMU_FAULT_ST_PREF           0x0008
+#define DSPMMU_FAULT_ST_PERM           0x0004
+#define DSPMMU_FAULT_ST_TLB_MISS       0x0002
+#define DSPMMU_FAULT_ST_TRANS          0x0001
+
+#define DSPMMU_IT_ACK_IT_ACK           0x0001
+
+#define DSPMMU_LOCK_BASE_MASK          0xfc00
+#define DSPMMU_LOCK_BASE_SHIFT         10
+#define DSPMMU_LOCK_VICTIM_MASK                0x03f0
+#define DSPMMU_LOCK_VICTIM_SHIFT       4
+
+#define DSPMMU_CAM_H_VA_TAG_H_MASK             0x0003
+
+#define DSPMMU_CAM_L_VA_TAG_L1_MASK            0xc000
+#define DSPMMU_CAM_L_VA_TAG_L2_MASK_1MB                0x0000
+#define DSPMMU_CAM_L_VA_TAG_L2_MASK_64KB       0x3c00
+#define DSPMMU_CAM_L_VA_TAG_L2_MASK_4KB                0x3fc0
+#define DSPMMU_CAM_L_VA_TAG_L2_MASK_1KB                0x3ff0
+#define DSPMMU_CAM_L_P                         0x0008
+#define DSPMMU_CAM_L_V                         0x0004
+#define DSPMMU_CAM_L_SLST_MASK                 0x0003
+#define DSPMMU_CAM_L_SLST_1MB                  0x0000
+#define DSPMMU_CAM_L_SLST_64KB                 0x0001
+#define DSPMMU_CAM_L_SLST_4KB                  0x0002
+#define DSPMMU_CAM_L_SLST_1KB                  0x0003
+
+#define DSPMMU_RAM_L_RAM_LSB_MASK      0xfc00
+#define DSPMMU_RAM_L_AP_MASK           0x0300
+#define DSPMMU_RAM_L_AP_NA             0x0000
+#define DSPMMU_RAM_L_AP_RO             0x0200
+#define DSPMMU_RAM_L_AP_FA             0x0300
+
+#define DSPMMU_GFLUSH_GFLUSH           0x0001
+
+#define DSPMMU_FLUSH_ENTRY_FLUSH_ENTRY 0x0001
+
+#define DSPMMU_LD_TLB_RD               0x0002
+#define DSPMMU_LD_TLB_LD               0x0001
+
+/*
+ * Mailbox
+ */
+#define MAILBOX_BASE                   (0xfffcf000)
+#define MAILBOX_ARM2DSP1               (MAILBOX_BASE + 0x00)
+#define MAILBOX_ARM2DSP1b              (MAILBOX_BASE + 0x04)
+#define MAILBOX_DSP2ARM1               (MAILBOX_BASE + 0x08)
+#define MAILBOX_DSP2ARM1b              (MAILBOX_BASE + 0x0c)
+#define MAILBOX_DSP2ARM2               (MAILBOX_BASE + 0x10)
+#define MAILBOX_DSP2ARM2b              (MAILBOX_BASE + 0x14)
+#define MAILBOX_ARM2DSP1_Flag          (MAILBOX_BASE + 0x18)
+#define MAILBOX_DSP2ARM1_Flag          (MAILBOX_BASE + 0x1c)
+#define MAILBOX_DSP2ARM2_Flag          (MAILBOX_BASE + 0x20)
+
+/*
+ * DSP ICR
+ */
+#define DSPREG_ICR_RESERVED_BITS       0xffc0
+#define DSPREG_ICR_EMIF_IDLE_DOMAIN    0x0020
+#define DSPREG_ICR_DPLL_IDLE_DOMAIN    0x0010
+#define DSPREG_ICR_PER_IDLE_DOMAIN     0x0008
+#define DSPREG_ICR_CACHE_IDLE_DOMAIN   0x0004
+#define DSPREG_ICR_DMA_IDLE_DOMAIN     0x0002
+#define DSPREG_ICR_CPU_IDLE_DOMAIN     0x0001
+
+#endif /* __OMAP_DSP_HARDWARE_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/ipbuf.c b/arch/arm/plat-omap/dsp/ipbuf.c
new file mode 100644 (file)
index 0000000..ebb482b
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/ipbuf.c
+ *
+ * IPBUF handler
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/06/06:  DSP Gateway version 3.3
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <asm/signal.h>
+#include <asm/arch/dsp.h>
+#include "dsp.h"
+#include "ipbuf.h"
+
+struct ipbuf **ipbuf;
+struct ipbcfg ipbcfg;
+struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
+static struct ipblink ipb_free = IPBLINK_INIT;
+static int ipbuf_sys_hold_mem_active;
+
+void ipbuf_stop(void)
+{
+       int i;
+
+       spin_lock(&ipb_free.lock);
+       INIT_IPBLINK(&ipb_free);
+       spin_unlock(&ipb_free.lock);
+
+       ipbcfg.ln = 0;
+       if (ipbuf) {
+               kfree(ipbuf);
+               ipbuf = NULL;
+       }
+       for (i = 0; i < ipbuf_sys_hold_mem_active; i++) {
+               dsp_mem_disable((void *)daram_base);
+       }
+       ipbuf_sys_hold_mem_active = 0;
+}
+
+int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
+{
+       unsigned long lsz_byte = ((unsigned long)lsz) << 1;
+       size_t size;
+       int ret = 0;
+       int i;
+
+       /*
+        * global IPBUF
+        */
+       if (((unsigned long)base) & 0x3) {
+               printk(KERN_ERR
+                      "omapdsp: global ipbuf address(0x%p) is not "
+                      "32-bit aligned!\n", base);
+               return -EINVAL;
+       }
+       size = lsz_byte * ln;
+       if (dsp_address_validate(base, size, "global ipbuf") < 0)
+               return -EINVAL;
+
+       ipbuf = kmalloc(sizeof(void *) * ln, GFP_KERNEL);
+       if (ipbuf == NULL) {
+               printk(KERN_ERR
+                      "omapdsp: memory allocation for ipbuf failed.\n");
+               return -ENOMEM;
+       }
+       for (i = 0; i < ln; i++) {
+               void *top, *btm;
+
+               top = base + (sizeof(struct ipbuf) + lsz_byte) * i;
+               btm = base + (sizeof(struct ipbuf) + lsz_byte) * (i+1) - 1;
+               ipbuf[i] = (struct ipbuf *)top;
+               if (((unsigned long)top & 0xfffe0000) !=
+                   ((unsigned long)btm & 0xfffe0000)) {
+                       /*
+                        * an ipbuf line should not cross
+                        * 64k-word boundary.
+                        */
+                       printk(KERN_ERR
+                              "omapdsp: ipbuf[%d] crosses 64k-word boundary!\n"
+                              "  @0x%p, size=0x%08lx\n", i, top, lsz_byte);
+                       ret = -EINVAL;
+                       goto free_out;
+               }
+       }
+       ipbcfg.ln       = ln;
+       ipbcfg.lsz      = lsz;
+       ipbcfg.base     = base;
+       ipbcfg.bsycnt   = ln;   /* DSP holds all ipbufs initially. */
+       ipbcfg.cnt_full = 0;
+
+       printk(KERN_INFO
+              "omapdsp: IPBUF configuration\n"
+              "           %d words * %d lines at 0x%p.\n",
+              ipbcfg.lsz, ipbcfg.ln, ipbcfg.base);
+
+       return ret;
+
+free_out:
+       kfree(ipbuf);
+       ipbuf = NULL;
+       return ret;
+}
+
+int ipbuf_sys_config(void *p, enum arm_dsp_dir dir)
+{
+       char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
+
+       if (((unsigned long)p) & 0x3) {
+               printk(KERN_ERR
+                      "omapdsp: system ipbuf(%s) address(0x%p) is "
+                      "not 32-bit aligned!\n", dir_str, p);
+               return -1;
+       }
+       if (dsp_address_validate(p, sizeof(struct ipbuf_sys),
+                                "system ipbuf(%s)", dir_str) < 0)
+               return -1;
+       if (dsp_mem_type(p, sizeof(struct ipbuf_sys)) != MEM_TYPE_EXTERN) {
+               printk(KERN_WARNING
+                      "omapdsp: system ipbuf(%s) is placed in"
+                      " DSP internal memory.\n"
+                      "         It will prevent DSP from idling.\n", dir_str);
+               ipbuf_sys_hold_mem_active++;
+               /*
+                * dsp_mem_enable() never fails because
+                * it has been already enabled in dspcfg process and
+                * this will just increment the usecount.
+                */
+               dsp_mem_enable((void *)daram_base);
+       }
+
+       if (dir == DIR_D2A)
+               ipbuf_sys_da = p;
+       else
+               ipbuf_sys_ad = p;
+       
+       return 0;
+}
+
+int ipbuf_p_validate(void *p, enum arm_dsp_dir dir)
+{
+       char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
+
+       if (((unsigned long)p) & 0x3) {
+               printk(KERN_ERR
+                      "omapdsp: private ipbuf(%s) address(0x%p) is "
+                      "not 32-bit aligned!\n", dir_str, p);
+               return -1;
+       }
+       return dsp_address_validate(p, sizeof(struct ipbuf_p),
+                                   "private ipbuf(%s)", dir_str);
+}
+
+/*
+ * Global IPBUF operations
+ */
+unsigned short get_free_ipbuf(unsigned char tid)
+{
+       unsigned short bid;
+
+       if (dsp_mem_enable_ipbuf() < 0)
+               return OMAP_DSP_BID_NULL;
+
+       spin_lock(&ipb_free.lock);
+
+       if (ipblink_empty(&ipb_free)) {
+               /* FIXME: wait on queue when not available.  */
+               bid = OMAP_DSP_BID_NULL;
+               goto out;
+       }
+       bid = ipb_free.top;
+       ipbuf[bid]->la = tid;   /* lock */
+       ipblink_del_top(&ipb_free, ipbuf);
+out:
+       spin_unlock(&ipb_free.lock);
+       dsp_mem_disable_ipbuf();
+
+       return bid;
+}
+
+void release_ipbuf(unsigned short bid)
+{
+       if (ipbuf[bid]->la == OMAP_DSP_TID_FREE) {
+               printk(KERN_WARNING
+                      "omapdsp: attempt to release unlocked IPBUF[%d].\n",
+                      bid);
+               /*
+                * FIXME: re-calc bsycnt
+                */
+               return;
+       }
+       ipbuf[bid]->la = OMAP_DSP_TID_FREE;
+       ipbuf[bid]->sa = OMAP_DSP_TID_FREE;
+       spin_lock(&ipb_free.lock);
+       ipblink_add_tail(&ipb_free, bid, ipbuf);
+       spin_unlock(&ipb_free.lock);
+}
+
+static int try_yld(unsigned short bid)
+{
+       int status;
+
+       ipbuf[bid]->sa = OMAP_DSP_TID_ANON;
+       status = dsp_mbsend(MBCMD(BKYLD), 0, bid);
+       if (status < 0) {
+               /* DSP is busy and ARM keeps this line. */
+               release_ipbuf(bid);
+               return status;
+       }
+
+       ipb_bsycnt_inc(&ipbcfg);
+       return 0;
+}
+
+/*
+ * balancing ipbuf lines with DSP
+ */
+static void do_balance_ipbuf(void)
+{
+       while (ipbcfg.bsycnt <= ipbcfg.ln / 4) {
+               unsigned short bid;
+
+               bid = get_free_ipbuf(OMAP_DSP_TID_ANON);
+               if (bid == OMAP_DSP_BID_NULL)
+                       return;
+               if (try_yld(bid) < 0)
+                       return;
+       }
+}
+
+static DECLARE_WORK(balance_ipbuf_work, (void (*)(void *))do_balance_ipbuf,
+                   NULL);
+
+void balance_ipbuf(void)
+{
+       schedule_work(&balance_ipbuf_work);
+}
+
+/* for process context */
+void unuse_ipbuf(unsigned short bid)
+{
+       if (ipbcfg.bsycnt > ipbcfg.ln / 4) {
+               /* we don't have enough IPBUF lines. let's keep it. */
+               release_ipbuf(bid);
+       } else {
+               /* we have enough IPBUF lines. let's return this line to DSP. */
+               ipbuf[bid]->la = OMAP_DSP_TID_ANON;
+               try_yld(bid);
+               balance_ipbuf();
+       }
+}
+
+/* for interrupt context */
+void unuse_ipbuf_nowait(unsigned short bid)
+{
+       release_ipbuf(bid);
+       balance_ipbuf();
+}
+
+/*
+ * functions called from mailbox1 interrupt routine
+ */
+
+void mbx1_err_ipbfull(void)
+{
+       ipbcfg.cnt_full++;
+}
+
+/*
+ * sysfs files
+ */
+static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       int len = 0;
+       unsigned short bid;
+
+       for (bid = 0; bid < ipbcfg.ln; bid++) {
+               unsigned short la = ipbuf[bid]->la;
+               unsigned short ld = ipbuf[bid]->ld;
+               unsigned short c  = ipbuf[bid]->c;
+
+               if (len > PAGE_SIZE - 100) {
+                       len += sprintf(buf + len, "out of buffer.\n");
+                       goto finish;
+               }
+
+               len += sprintf(buf + len, "ipbuf[%d]: adr = 0x%p\n",
+                              bid, ipbuf[bid]);
+               if (la == OMAP_DSP_TID_FREE) {
+                       len += sprintf(buf + len,
+                                      "  DSPtask[%d]->Linux "
+                                      "(already read and now free for Linux)\n",
+                                      ld);
+               } else if (ld == OMAP_DSP_TID_FREE) {
+                       len += sprintf(buf + len,
+                                      "  Linux->DSPtask[%d] "
+                                      "(already read and now free for DSP)\n",
+                                      la);
+               } else if (ipbuf_is_held(ld, bid)) {
+                       len += sprintf(buf + len,
+                                      "  DSPtask[%d]->Linux "
+                                      "(waiting to be read)\n"
+                                      "  count = %d\n", ld, c);
+               } else {
+                       len += sprintf(buf + len,
+                                      "  Linux->DSPtask[%d] "
+                                      "(waiting to be read)\n"
+                                      "  count = %d\n", la, c);
+               }
+       }
+
+       len += sprintf(buf + len, "\nFree IPBUF link: ");
+       spin_lock(&ipb_free.lock);
+       ipblink_for_each(bid, &ipb_free, ipbuf) {
+               len += sprintf(buf + len, "%d ", bid);
+       }
+       spin_unlock(&ipb_free.lock);
+       len += sprintf(buf + len, "\n");
+       len += sprintf(buf + len, "IPBFULL error count: %ld\n",
+                      ipbcfg.cnt_full);
+
+finish:
+       return len;
+}
+
+struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
diff --git a/arch/arm/plat-omap/dsp/ipbuf.h b/arch/arm/plat-omap/dsp/ipbuf.h
new file mode 100644 (file)
index 0000000..77826f4
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/ipbuf.h
+ *
+ * Header for IPBUF
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/05/17:  DSP Gateway version 3.3
+ */
+
+struct ipbuf {
+       unsigned short c;       /* count */
+       unsigned short next;    /* link */
+       unsigned short la;      /* lock owner (ARM side) */
+       unsigned short sa;      /* sync word (ARM->DSP) */
+       unsigned short ld;      /* lock owner (DSP side) */
+       unsigned short sd;      /* sync word (DSP->ARM) */
+       unsigned char d[0];     /* data */
+};
+
+struct ipbuf_p {
+       unsigned short c;       /* count */
+       unsigned short s;       /* sync word */
+       unsigned short al;      /* data address lower */
+       unsigned short ah;      /* data address upper */
+};
+
+struct ipbuf_sys {
+       unsigned short s;       /* sync word */
+       unsigned short d[31];   /* data */
+};
+
+struct ipbcfg {
+       unsigned short ln;
+       unsigned short lsz;
+       void *base;
+       unsigned short bsycnt;
+       unsigned long cnt_full; /* count of IPBFULL error */
+};
+
+extern struct ipbuf **ipbuf;
+extern struct ipbcfg ipbcfg;
+extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
+
+#define ipb_bsycnt_inc(ipbcfg) \
+       do { \
+               disable_irq(INT_D2A_MB1); \
+               (ipbcfg)->bsycnt++; \
+               enable_irq(INT_D2A_MB1); \
+       } while(0)
+
+#define ipb_bsycnt_dec(ipbcfg) \
+       do { \
+               disable_irq(INT_D2A_MB1); \
+               (ipbcfg)->bsycnt--; \
+               enable_irq(INT_D2A_MB1); \
+       } while(0)
+
+#define dsp_mem_enable_ipbuf() dsp_mem_enable(ipbcfg.base)
+#define dsp_mem_disable_ipbuf()        dsp_mem_disable(ipbcfg.base)
+
+struct ipblink {
+       spinlock_t lock;
+       unsigned short top;
+       unsigned short tail;
+};
+
+#define IPBLINK_INIT { \
+               .lock = SPIN_LOCK_UNLOCKED, \
+               .top  = OMAP_DSP_BID_NULL, \
+               .tail = OMAP_DSP_BID_NULL, \
+       }
+
+#define INIT_IPBLINK(link) \
+       do { \
+               spin_lock_init(&(link)->lock); \
+               (link)->top  = OMAP_DSP_BID_NULL; \
+               (link)->tail = OMAP_DSP_BID_NULL; \
+       } while(0)
+
+#define ipblink_empty(link)    ((link)->top == OMAP_DSP_BID_NULL)
+
+static __inline__ void ipblink_del_top(struct ipblink *link,
+                                      struct ipbuf **ipbuf)
+{
+       struct ipbuf *bufp = ipbuf[link->top];
+
+       if ((link->top = bufp->next) == OMAP_DSP_BID_NULL)
+               link->tail = OMAP_DSP_BID_NULL;
+       else
+               bufp->next = OMAP_DSP_BID_NULL;
+}
+
+static __inline__ void ipblink_add_tail(struct ipblink *link,
+                                       unsigned short bid,
+                                       struct ipbuf **ipbuf)
+{
+       if (ipblink_empty(link))
+               link->top = bid;
+       else
+               ipbuf[link->tail]->next = bid;
+       link->tail = bid;
+}
+
+static __inline__ void ipblink_add_pvt(struct ipblink *link)
+{
+       link->top  = OMAP_DSP_BID_PVT;
+       link->tail = OMAP_DSP_BID_PVT;
+}
+
+static __inline__ void ipblink_del_pvt(struct ipblink *link)
+{
+       link->top  = OMAP_DSP_BID_NULL;
+       link->tail = OMAP_DSP_BID_NULL;
+}
+
+#define ipblink_for_each(bid, link, ipbuf) \
+       for (bid = (link)->top; bid != OMAP_DSP_BID_NULL; bid = ipbuf[bid]->next)
diff --git a/arch/arm/plat-omap/dsp/mblog.c b/arch/arm/plat-omap/dsp/mblog.c
new file mode 100644 (file)
index 0000000..0edf070
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/mblog.c
+ *
+ * OMAP DSP driver Mailbox log module
+ *
+ * Copyright (C) 2003-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2005/05/18:  DSP Gateway version 3.3
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <asm/irq.h>
+#include <asm/arch/dsp.h>
+#include "dsp.h"
+
+#define RLCMD(nm)      OMAP_DSP_MBCMD_RUNLEVEL_##nm
+#define KFUNCCMD(nm)   OMAP_DSP_MBCMD_KFUNC_##nm
+#define PMCMD(nm)      OMAP_DSP_MBCMD_PM_##nm
+#define CFGCMD(nm)     OMAP_DSP_MBCMD_DSPCFG_##nm
+#define REGCMD(nm)     OMAP_DSP_MBCMD_REGRW_##nm
+#define VICMD(nm)      OMAP_DSP_MBCMD_VARID_##nm
+#define EID(nm)                OMAP_DSP_EID_##nm
+
+char *subcmd_name(struct mbcmd *mb)
+{
+       unsigned char cmd_h = mb->cmd_h;
+       unsigned char cmd_l = mb->cmd_l;
+       char *s;
+
+       switch (cmd_h) {
+       case MBCMD(RUNLEVEL):
+               s = (cmd_l == RLCMD(USER))     ? "USER":
+                   (cmd_l == RLCMD(SUPER))    ? "SUPER":
+                   (cmd_l == RLCMD(RECOVERY)) ? "RECOVERY":
+                   NULL;
+               break;
+       case MBCMD(PM):
+               s = (cmd_l == PMCMD(DISABLE)) ? "DISABLE":
+                   (cmd_l == PMCMD(ENABLE))  ? "ENABLE":
+                   NULL;
+               break;
+       case MBCMD(KFUNC):
+               s = (cmd_l == KFUNCCMD(FBCTL)) ? "FBCTL":
+                   NULL;
+               break;
+       case MBCMD(DSPCFG):
+               {
+                       unsigned char cfgc = cmd_l & 0x7f;
+                       s = (cfgc == CFGCMD(REQ))     ? "REQ":
+                           (cfgc == CFGCMD(SYSADRH)) ? "SYSADRH":
+                           (cfgc == CFGCMD(SYSADRL)) ? "SYSADRL":
+                           (cfgc == CFGCMD(ABORT))   ? "ABORT":
+                           (cfgc == CFGCMD(PROTREV)) ? "PROTREV":
+                           NULL;
+                       break;
+               }
+       case MBCMD(REGRW):
+               s = (cmd_l == REGCMD(MEMR)) ? "MEMR":
+                   (cmd_l == REGCMD(MEMW)) ? "MEMW":
+                   (cmd_l == REGCMD(IOR))  ? "IOR":
+                   (cmd_l == REGCMD(IOW))  ? "IOW":
+                   (cmd_l == REGCMD(DATA)) ? "DATA":
+                   NULL;
+               break;
+       case MBCMD(GETVAR):
+       case MBCMD(SETVAR):
+               s = (cmd_l == VICMD(ICRMASK))  ? "ICRMASK":
+                   (cmd_l == VICMD(LOADINFO)) ? "LOADINFO":
+                   NULL;
+               break;
+       case MBCMD(ERR):
+               s = (cmd_l == EID(BADTID))     ? "BADTID":
+                   (cmd_l == EID(BADTCN))     ? "BADTCN":
+                   (cmd_l == EID(BADBID))     ? "BADBID":
+                   (cmd_l == EID(BADCNT))     ? "BADCNT":
+                   (cmd_l == EID(NOTLOCKED))  ? "NOTLOCKED":
+                   (cmd_l == EID(STVBUF))     ? "STVBUF":
+                   (cmd_l == EID(BADADR))     ? "BADADR":
+                   (cmd_l == EID(BADTCTL))    ? "BADTCTL":
+                   (cmd_l == EID(BADPARAM))   ? "BADPARAM":
+                   (cmd_l == EID(FATAL))      ? "FATAL":
+                   (cmd_l == EID(WDT))        ? "WDT":
+                   (cmd_l == EID(NOMEM))      ? "NOMEM":
+                   (cmd_l == EID(NORES))      ? "NORES":
+                   (cmd_l == EID(IPBFULL))    ? "IPBFULL":
+                   (cmd_l == EID(TASKNOTRDY)) ? "TASKNOTRDY":
+                   (cmd_l == EID(TASKBSY))    ? "TASKBSY":
+                   (cmd_l == EID(TASKERR))    ? "TASKERR":
+                   (cmd_l == EID(BADCFGTYP))  ? "BADCFGTYP":
+                   (cmd_l == EID(DEBUG))      ? "DEBUG":
+                   (cmd_l == EID(BADSEQ))     ? "BADSEQ":
+                   (cmd_l == EID(BADCMD))     ? "BADCMD":
+                   NULL;
+               break;
+       default:
+               s = NULL;
+       }
+
+       return s;
+}
+
+/* output of show() method should fit to PAGE_SIZE */
+#define MBLOG_DEPTH    64
+
+struct mblogent {
+       unsigned long jiffies;
+       unsigned short cmd;
+       unsigned short data;
+       enum arm_dsp_dir dir;
+};
+
+static struct {
+       spinlock_t lock;
+       int wp;
+       unsigned long cnt, cnt_ad, cnt_da;
+       struct mblogent ent[MBLOG_DEPTH];
+} mblog;
+
+void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir)
+{
+       struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
+       struct mblogent *ent;
+
+       spin_lock(&mblog.lock);
+       ent = &mblog.ent[mblog.wp];
+       ent->jiffies = jiffies;
+       ent->cmd     = mb_hw->cmd;
+       ent->data    = mb_hw->data;
+       ent->dir     = dir;
+       if (mblog.cnt < 0xffffffff)
+               mblog.cnt++;
+       switch (dir) {
+       case DIR_A2D:
+               if (mblog.cnt_ad < 0xffffffff)
+                       mblog.cnt_ad++;
+               break;
+       case DIR_D2A:
+               if (mblog.cnt_da < 0xffffffff)
+                       mblog.cnt_da++;
+               break;
+       }
+       if (++mblog.wp == MBLOG_DEPTH)
+               mblog.wp = 0;
+       spin_unlock(&mblog.lock);
+}
+
+/*
+ * sysfs file
+ */
+static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       int len = 0;
+       int wp;
+       int i;
+
+       spin_lock(&mblog.lock);
+
+       wp = mblog.wp;
+       len += sprintf(buf + len,
+                      "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
+                      mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
+       if (mblog.cnt == 0)
+               goto done;
+
+       len += sprintf(buf + len, "          ARM -> DSP   ARM <- DSP\n");
+       len += sprintf(buf + len, "jiffies  q cmd  data q cmd  data\n");
+       i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
+       do {
+               struct mblogent *ent = &mblog.ent[i];
+               union {
+                       struct mbcmd sw;
+                       struct mbcmd_hw hw;
+               } mb = {
+                       .hw.cmd  = ent->cmd,
+                       .hw.data = ent->data
+               };
+               char *subname;
+               const struct cmdinfo *ci = cmdinfo[mb.sw.cmd_h];
+
+               len += sprintf(buf + len,
+                              (ent->dir == DIR_A2D) ?
+                               "%08lx %d %04x %04x             ":
+                               "%08lx             %d %04x %04x ",
+                              ent->jiffies, mb.sw.seq, ent->cmd, ent->data);
+               switch (ci->cmd_l_type) {
+               case CMD_L_TYPE_SUBCMD:
+                       if ((subname = subcmd_name(&mb.sw)) == NULL)
+                               subname = "Unknown";
+                       len += sprintf(buf + len, "%s:%s\n",
+                                      ci->name, subname);
+                       break;
+               case CMD_L_TYPE_TID:
+                       len += sprintf(buf + len, "%s:task %d\n",
+                                      ci->name, mb.sw.cmd_l);
+                       break;
+               case CMD_L_TYPE_NULL:
+                       len += sprintf(buf + len, "%s\n", ci->name);
+                       break;
+               }
+
+               if (++i == MBLOG_DEPTH)
+                       i = 0;
+       } while (i != wp);
+
+done:
+       spin_unlock(&mblog.lock);
+
+       return len;
+}
+
+static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
+
+#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
+void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir)
+{
+       const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
+       char *dir_str;
+       char *subname;
+
+       dir_str = (dir == DIR_A2D) ? "sending" : "receiving";
+       switch (ci->cmd_l_type) {
+       case CMD_L_TYPE_SUBCMD:
+               if ((subname = subcmd_name(mb)) == NULL)
+                       subname = "Unknown";
+               printk(KERN_DEBUG
+                      "mbx: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
+                      dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+                      ci->name, subname, mb->data);
+               break;
+       case CMD_L_TYPE_TID:
+               printk(KERN_DEBUG
+                      "mbx: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
+                      dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+                      ci->name, mb->cmd_l, mb->data);
+               break;
+       case CMD_L_TYPE_NULL:
+               printk(KERN_DEBUG
+                      "mbx: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
+                      dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+                      ci->name, mb->data);
+               break;
+       }
+}
+#endif /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
+
+void __init mblog_init(void)
+{
+       spin_lock_init(&mblog.lock);
+       device_create_file(&dsp_device.dev, &dev_attr_mblog);
+}
+
+void mblog_exit(void)
+{
+       device_remove_file(&dsp_device.dev, &dev_attr_mblog);
+}
diff --git a/arch/arm/plat-omap/dsp/proclist.h b/arch/arm/plat-omap/dsp/proclist.h
new file mode 100644 (file)
index 0000000..7214317
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/proclist.h
+ *
+ * Linux task list handler
+ *
+ * Copyright (C) 2004,2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2004/11/22:  DSP Gateway version 3.3
+ */
+
+struct proc_list {
+       struct list_head list_head;
+       struct task_struct *tsk;
+       unsigned int cnt;
+};
+
+static __inline__ void proc_list_add(struct list_head *list,
+                                    struct task_struct *tsk)
+{
+       struct list_head *ptr;
+       struct proc_list *pl;
+       struct proc_list *new;
+
+       list_for_each(ptr, list) {
+               pl = list_entry(ptr, struct proc_list, list_head);
+               if (pl->tsk == tsk) {
+                       /*
+                        * this process has opened DSP devices multi time
+                        */
+                       pl->cnt++;
+                       return;
+               }
+       }
+
+       new = kmalloc(sizeof(struct proc_list), GFP_KERNEL);
+       new->tsk = tsk;
+       new->cnt = 1;
+       list_add_tail(&new->list_head, list);
+}
+
+static __inline__ void proc_list_del(struct list_head *list,
+                                    struct task_struct *tsk)
+{
+       struct list_head *ptr;
+       struct proc_list *pl;
+
+       list_for_each(ptr, list) {
+               pl = list_entry(ptr, struct proc_list, list_head);
+               if (pl->tsk == tsk) {
+                       if (--pl->cnt == 0) {
+                               list_del(&pl->list_head);
+                               kfree(pl);
+                       }
+                       return;
+               }
+       }
+}
+
+static __inline__ void proc_list_flush(struct list_head *list)
+{
+       struct proc_list *pl;
+
+       while (!list_empty(list)) {
+               pl = list_entry(list->next, struct proc_list, list_head);
+               list_del(&pl->list_head);
+               kfree(pl);
+       }
+}
diff --git a/arch/arm/plat-omap/dsp/task.c b/arch/arm/plat-omap/dsp/task.c
new file mode 100644 (file)
index 0000000..be6cdce
--- /dev/null
@@ -0,0 +1,2829 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/task.c
+ *
+ * OMAP DSP task device driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * mmap function by Hiroo Ishikawa <ext-hiroo.ishikawa@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
+ *
+ * 2005/07/26:  DSP Gateway version 3.3
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/signal.h>
+#include <asm/irq.h>
+#include <asm/ioctls.h>
+#include <asm/arch/dsp.h>
+#include "uaccess_dsp.h"
+#include "dsp.h"
+#include "ipbuf.h"
+#include "fifo.h"
+#include "proclist.h"
+
+#define is_aligned(adr,align)  (!((adr)&((align)-1)))
+
+/*
+ * taskdev.state: device state machine
+ * NOTASK:     task is not attached.
+ * ATTACHED:   task is attached.
+ * GARBAGE:    task is detached. waiting for all processes to close this device.
+ * ADDREQ:     requesting for tadd
+ * DELREQ:     requesting for tdel. no process is opening this device.
+ * ADDFAIL:    tadd failed.
+ * ADDING:     tadd in process.
+ * DELING:     tdel in process.
+ * KILLING:    tkill in process.
+ */
+#define devstate_name(stat) (\
+       ((stat) & OMAP_DSP_DEVSTATE_NOTASK)   ? "NOTASK" :\
+       ((stat) & OMAP_DSP_DEVSTATE_ATTACHED) ? "ATTACHED" :\
+       ((stat) & OMAP_DSP_DEVSTATE_GARBAGE)  ? "GARBAGE" :\
+       ((stat) & OMAP_DSP_DEVSTATE_INVALID)  ? "INVALID" :\
+       ((stat) & OMAP_DSP_DEVSTATE_ADDREQ)   ? "ADDREQ" :\
+       ((stat) & OMAP_DSP_DEVSTATE_DELREQ)   ? "DELREQ" :\
+       ((stat) & OMAP_DSP_DEVSTATE_ADDFAIL)  ? "ADDFAIL" :\
+       ((stat) & OMAP_DSP_DEVSTATE_ADDING)   ? "ADDING" :\
+       ((stat) & OMAP_DSP_DEVSTATE_DELING)   ? "DELING" :\
+       ((stat) & OMAP_DSP_DEVSTATE_KILLING)  ? "KILLING" :\
+                                               "unknown")
+
+struct taskdev {
+       struct bus_type *bus;
+//     struct device_driver *driver;
+       struct device dev;      /* Generic device interface */
+
+       long state;
+       spinlock_t state_lock;
+       wait_queue_head_t state_wait_q;
+       unsigned int usecount;
+       char name[OMAP_DSP_TNM_LEN];
+       struct file_operations fops;
+       struct list_head proc_list;
+       struct dsptask *task;
+
+       /* read stuff */
+       wait_queue_head_t read_wait_q;
+       struct semaphore read_sem;
+
+       /* write stuff */
+       wait_queue_head_t write_wait_q;
+       struct semaphore write_sem;
+
+       /* ioctl stuff */
+       wait_queue_head_t ioctl_wait_q;
+       struct semaphore ioctl_sem;
+
+       /* device lock */
+       struct semaphore lock_sem;
+       pid_t lock_pid;
+};
+
+#define to_taskdev(n) container_of(n, struct taskdev, dev)
+
+struct rcvdt_bk_struct {
+       struct ipblink link;
+       unsigned int rp;
+       struct ipbuf_p *ipbuf_pvt_r;
+};
+
+struct dsptask {
+       enum {
+               TASK_STATE_ERR = 0,
+               TASK_STATE_READY,
+               TASK_STATE_CFGREQ
+       } state;
+       unsigned char tid;
+       char name[OMAP_DSP_TNM_LEN];
+       unsigned short ttyp;
+       struct taskdev *dev;
+
+       /* read stuff */
+       union {
+               struct fifo_struct fifo;        /* for active word */
+               struct rcvdt_bk_struct bk;
+       } rcvdt;
+
+       /* write stuff */
+       size_t wsz;
+       spinlock_t wsz_lock;
+       struct ipbuf_p *ipbuf_pvt_w;    /* for private block */
+
+       /* tctl stuff */
+       int tctl_stat;
+
+       /* mmap stuff */
+       void *map_base;
+       size_t map_length;
+};
+
+#define sndtyp_acv(ttyp)       ((ttyp) & OMAP_DSP_TTYP_ASND)
+#define sndtyp_psv(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_ASND))
+#define sndtyp_bk(ttyp)                ((ttyp) & OMAP_DSP_TTYP_BKDM)
+#define sndtyp_wd(ttyp)                (!((ttyp) & OMAP_DSP_TTYP_BKDM))
+#define sndtyp_pvt(ttyp)       ((ttyp) & OMAP_DSP_TTYP_PVDM)
+#define sndtyp_gbl(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_PVDM))
+#define rcvtyp_acv(ttyp)       ((ttyp) & OMAP_DSP_TTYP_ARCV)
+#define rcvtyp_psv(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_ARCV))
+#define rcvtyp_bk(ttyp)                ((ttyp) & OMAP_DSP_TTYP_BKMD)
+#define rcvtyp_wd(ttyp)                (!((ttyp) & OMAP_DSP_TTYP_BKMD))
+#define rcvtyp_pvt(ttyp)       ((ttyp) & OMAP_DSP_TTYP_PVMD)
+#define rcvtyp_gbl(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_PVMD))
+
+static int dsp_rmdev_minor(unsigned char minor);
+static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
+static void taskdev_delete(unsigned char minor);
+static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
+static void taskdev_detach_task(struct taskdev *dev);
+static int dsp_tdel_bh(unsigned char minor, unsigned short type);
+
+static ssize_t devname_show(struct device *d, struct device_attribute *attr,
+                           char *buf);
+static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
+                            char *buf);
+static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
+                             char *buf);
+static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
+                            char *buf);
+static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
+                        char *buf);
+static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
+                          char *buf);
+static int fifosz_store(struct device *d, struct device_attribute *attr,
+                       const char *buf, size_t count);
+static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
+                           char *buf);
+static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
+                           char *buf);
+static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
+                       char *buf);
+static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
+                        char *buf);
+
+static struct device_attribute dev_attr_devname = __ATTR_RO(devname);
+static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate);
+static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
+static struct device_attribute dev_attr_fifosz = 
+       __ATTR(fifosz, S_IWUGO | S_IRUGO, fifosz_show, fifosz_store);
+static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt);
+static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname);
+static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp);
+static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink);
+static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz);
+static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap);
+
+static struct bus_type dsptask_bus = {
+       .name = "dsptask",
+};
+
+static struct class *dsp_task_class;
+static struct taskdev *taskdev[TASKDEV_MAX];
+static struct dsptask *dsptask[TASKDEV_MAX];
+static DECLARE_MUTEX(cfg_sem);
+static unsigned short cfg_cmd;
+static unsigned char cfg_tid;
+static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
+static unsigned char n_task;
+static void *heap;
+
+#define devstate_lock(dev, devstate)   devstate_lock_timeout(dev, devstate, 0)
+
+/*
+ * devstate_lock_timeout():
+ * when called with timeout > 0, dev->state can be diffeent from what you want.
+ */
+static int devstate_lock_timeout(struct taskdev *dev, long devstate,
+                                int timeout)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       long current_state = current->state;
+       int ret = 0;
+
+       spin_lock(&dev->state_lock);
+       add_wait_queue(&dev->state_wait_q, &wait);
+       while (!(dev->state & devstate)) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               spin_unlock(&dev->state_lock);
+               if (timeout) {
+                       if ((timeout = schedule_timeout(timeout)) == 0) {
+                               /* timeout */
+                               spin_lock(&dev->state_lock);
+                               break;
+                       }
+               }
+               else
+                       schedule();
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       break;
+               }
+               spin_lock(&dev->state_lock);
+       }
+       remove_wait_queue(&dev->state_wait_q, &wait);
+       set_current_state(current_state);
+       return ret;
+}
+
+static __inline__ void devstate_unlock(struct taskdev *dev)
+{
+       spin_unlock(&dev->state_lock);
+}
+
+static __inline__ int down_tasksem_interruptible(struct taskdev *dev,
+                                                struct semaphore *sem)
+{
+       int ret;
+
+       if (dev->lock_pid == current->pid) {
+               /* this process has lock */
+               ret = down_interruptible(sem);
+       } else {
+               if ((ret = down_interruptible(&dev->lock_sem)) != 0)
+                       return ret;
+               ret = down_interruptible(sem);
+               up(&dev->lock_sem);
+       }
+       return ret;
+}
+
+static int dsp_task_flush_buf(struct dsptask *task)
+{
+       unsigned short ttyp = task->ttyp;
+
+       if (sndtyp_wd(ttyp)) {
+               /* word receiving */
+               flush_fifo(&task->rcvdt.fifo);
+       } else {
+               /* block receiving */
+               struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
+
+               spin_lock(&rcvdt->link.lock);
+               if (sndtyp_gbl(ttyp)) {
+                       /* global IPBUF */
+                       while (!ipblink_empty(&rcvdt->link)) {
+                               unsigned short bid = rcvdt->link.top;
+                               ipblink_del_top(&rcvdt->link, ipbuf);
+                               unuse_ipbuf(bid);
+                       }
+               } else {
+                       /* private IPBUF */
+                       if (!ipblink_empty(&rcvdt->link)) {
+                               ipblink_del_pvt(&rcvdt->link);
+                               release_ipbuf_pvt(rcvdt->ipbuf_pvt_r);
+                       }
+               }
+               spin_unlock(&rcvdt->link.lock);
+       }
+
+       return 0;
+}
+
+static int dsp_task_set_fifosz(struct dsptask *task, unsigned long sz)
+{
+       unsigned short ttyp = task->ttyp;
+       int stat;
+
+       if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
+               printk(KERN_ERR
+                      "omapdsp: buffer size can be changed only for "
+                      "active word sending task.\n");
+               return -EINVAL;
+       }
+       if ((sz == 0) || (sz & 1)) {
+               printk(KERN_ERR "omapdsp: illegal buffer size! (%ld)\n"
+                               "it must be even and non-zero value.\n", sz);
+               return -EINVAL;
+       }
+
+       stat = realloc_fifo(&task->rcvdt.fifo, sz);
+       if (stat == -EBUSY) {
+               printk(KERN_ERR "omapdsp: buffer is not empty!\n");
+               return stat;
+       } else if (stat < 0) {
+               printk(KERN_ERR
+                      "omapdsp: unable to change receive buffer size. "
+                      "(%ld bytes for %s)\n", sz, task->name);
+               return stat;
+       }
+
+       return 0;
+}
+
+static int taskdev_lock(struct taskdev *dev)
+{
+       if (down_interruptible(&dev->lock_sem))
+               return -ERESTARTSYS;
+       dev->lock_pid = current->pid;
+       return 0;
+}
+
+static int taskdev_unlock(struct taskdev *dev)
+{
+       if (dev->lock_pid != current->pid) {
+               printk(KERN_ERR
+                      "omapdsp: an illegal process attempted to "
+                      "unlock the dsptask lock!\n");
+               return -EINVAL;
+       }
+       dev->lock_pid = 0;
+       up(&dev->lock_sem);
+       return 0;
+}
+
+static int dsp_task_config(struct dsptask *task, unsigned char tid)
+{
+       unsigned short ttyp;
+       struct mbcmd mb;
+       int ret;
+
+       task->tid = tid;
+       dsptask[tid] = task;
+
+       /* TCFG request */
+       task->state = TASK_STATE_CFGREQ;
+       if (down_interruptible(&cfg_sem)) {
+               ret = -ERESTARTSYS;
+               goto fail_out;
+       }
+       cfg_cmd = MBCMD(TCFG);
+       mbcmd_set(mb, MBCMD(TCFG), tid, 0);
+       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+       cfg_cmd = 0;
+       up(&cfg_sem);
+
+       if (task->state != TASK_STATE_READY) {
+               printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
+               ret = -EINVAL;
+               goto fail_out;
+       }
+
+       if (strlen(task->name) <= 1)
+               sprintf(task->name, "%d", tid);
+       printk(KERN_INFO "omapdsp: task %d: name %s\n", tid, task->name);
+
+       ttyp = task->ttyp;
+
+       /*
+        * task info sanity check
+        */
+
+       /* task type check */
+       if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) {
+               printk(KERN_ERR "omapdsp: illegal task type(0x%04x), tid=%d\n",
+                      tid, ttyp);
+               ret = -EINVAL;
+               goto fail_out;
+       }
+
+       /* private buffer address check */
+       if (sndtyp_pvt(ttyp) &&
+           (ipbuf_p_validate(task->rcvdt.bk.ipbuf_pvt_r, DIR_D2A) < 0)) {
+               ret = -EINVAL;
+               goto fail_out;
+       }
+       if (rcvtyp_pvt(ttyp) &&
+           (ipbuf_p_validate(task->ipbuf_pvt_w, DIR_A2D) < 0)) {
+               ret = -EINVAL;
+               goto fail_out;
+       }
+       
+       /* mmap buffer configuration check */
+       if ((task->map_length > 0) &&
+           ((!is_aligned((unsigned long)task->map_base, PAGE_SIZE)) ||
+            (!is_aligned(task->map_length, PAGE_SIZE)) ||
+            (dsp_mem_type(task->map_base, task->map_length) != MEM_TYPE_EXTERN))) {
+               printk(KERN_ERR
+                      "omapdsp: illegal mmap buffer address(0x%p) or "
+                      "length(0x%x).\n"
+                      "  It needs to be page-aligned and located at "
+                      "external memory.\n",
+                      task->map_base, task->map_length);
+               ret = -EINVAL;
+               goto fail_out;
+       }
+
+       /*
+        * initialization
+        */
+
+       /* read initialization */
+       if (sndtyp_wd(ttyp)) {
+               /* word */
+               size_t fifosz;
+
+               fifosz = sndtyp_psv(ttyp) ? 2 : /* passive */
+                                           32; /* active */
+               if (init_fifo(&task->rcvdt.fifo, fifosz) < 0) {
+                       printk(KERN_ERR
+                              "omapdsp: unable to allocate receive buffer. "
+                              "(%d bytes for %s)\n", fifosz, task->name);
+                       ret = -ENOMEM;
+                       goto fail_out;
+               }
+       } else {
+               /* block */
+               INIT_IPBLINK(&task->rcvdt.bk.link);
+               task->rcvdt.bk.rp = 0;
+       }
+
+       /* write initialization */
+       spin_lock_init(&task->wsz_lock);
+       task->wsz = rcvtyp_acv(ttyp) ? 0 :              /* active */
+                   rcvtyp_wd(ttyp)  ? 2 :              /* passive word */
+                                      ipbcfg.lsz*2;    /* passive block */
+
+       return 0;
+
+fail_out:
+       dsptask[tid] = NULL;
+       return ret;
+}
+
+static void dsp_task_init(struct dsptask *task)
+{
+       dsp_mbsend(MBCMD(TCTL), task->tid, OMAP_DSP_MBCMD_TCTL_TINIT);
+}
+
+int dsp_task_config_all(unsigned char n)
+{
+       int i, ret;
+       struct taskdev *devheap;
+       struct dsptask *taskheap;
+       size_t devheapsz, taskheapsz;
+
+       memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
+       memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
+
+       n_task = n;
+       printk(KERN_INFO "omapdsp: found %d task(s)\n", n_task);
+       if (n_task == 0)
+               return 0;
+
+       /*
+        * reducing kmalloc!
+        */
+       devheapsz  = sizeof(struct taskdev) * n_task;
+       taskheapsz = sizeof(struct dsptask) * n_task;
+       heap = kmalloc(devheapsz + taskheapsz, GFP_KERNEL);
+       if (heap == NULL) {
+               n_task = 0;
+               return -ENOMEM;
+       }
+       memset(heap, 0, devheapsz + taskheapsz);
+       devheap  = heap;
+       taskheap = heap + devheapsz;
+
+       for (i = 0; i < n_task; i++) {
+               struct taskdev *dev  = &devheap[i];
+               struct dsptask *task = &taskheap[i];
+
+               if ((ret = dsp_task_config(task, i)) < 0)
+                       return ret;
+               if ((ret = taskdev_init(dev, task->name, i)) < 0)
+                       return ret;
+               taskdev_attach_task(dev, task);
+               dsp_task_init(task);
+               printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
+       }
+
+       return 0;
+}
+
+static void dsp_task_unconfig(struct dsptask *task)
+{
+       unsigned char tid = task->tid;
+
+       preempt_disable();
+       dsp_task_flush_buf(task);
+       if (sndtyp_wd(task->ttyp) && (task->state == TASK_STATE_READY))
+               free_fifo(&task->rcvdt.fifo);
+       dsptask[tid] = NULL;
+       preempt_enable();
+}
+
+void dsp_task_unconfig_all(void)
+{
+       unsigned char minor;
+       unsigned char tid;
+       struct dsptask *task;
+
+       for (minor = 0; minor < n_task; minor++) {
+               /*
+                * taskdev[minor] can be NULL in case of
+                * configuration failure
+                */
+               if (taskdev[minor])
+                       taskdev_delete(minor);
+       }
+       for (; minor < TASKDEV_MAX; minor++) {
+               if (taskdev[minor])
+                       dsp_rmdev_minor(minor);
+       }
+
+       for (tid = 0; tid < n_task; tid++) {
+               /*
+                * dsptask[tid] can be NULL in case of
+                * configuration failure
+                */
+               task = dsptask[tid];
+               if (task)
+                       dsp_task_unconfig(task);
+       }
+       for (; tid < TASKDEV_MAX; tid++) {
+               task = dsptask[tid];
+               if (task) {
+                       /*
+                        * on-demand tasks should be deleted in
+                        * rmdev_minor(), but just in case.
+                        */
+                       dsp_task_unconfig(task);
+                       kfree(task);
+               }
+       }
+
+       if (heap) {
+               kfree(heap);
+               heap = NULL;
+       }
+
+       n_task = 0;
+}
+
+static struct device_driver dsptask_driver = {
+       .name   = "dsptask",
+       .bus    = &dsptask_bus,
+};
+
+unsigned char dsp_task_count(void)
+{
+       return n_task;
+}
+
+int dsp_taskmod_busy(void)
+{
+       struct taskdev *dev;
+       unsigned char minor;
+
+       for (minor = 0; minor < TASKDEV_MAX; minor++) {
+               dev = taskdev[minor];
+               if (dev == NULL)
+                       continue;
+               if (dev->usecount > 0) {
+                       printk("dsp_taskmod_busy(): %s: usecount=%d\n",
+                              dev->name, dev->usecount);
+                       return 1;
+               }
+/*
+               if ((dev->state & (OMAP_DSP_DEVSTATE_ADDREQ |
+                                  OMAP_DSP_DEVSTATE_DELREQ)) {
+*/
+               if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ) {
+                       printk("dsp_taskmod_busy(): %s is in %s\n",
+                              dev->name, devstate_name(dev->state));
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/*
+ * DSP task device file operations
+ */
+static ssize_t dsp_task_read_wd_acv(struct file *file, char *buf, size_t count,
+                                   loff_t *ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       int have_devstate_lock = 0;
+       int ret = 0;
+
+       if (count == 0) {
+               return 0;
+       } else if (count & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: odd count is illegal for DSP task device.\n");
+               return -EINVAL;
+       }
+
+       if (down_tasksem_interruptible(dev, &dev->read_sem))
+               return -ERESTARTSYS;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       have_devstate_lock = 1;
+
+       if (fifo_empty(&dev->task->rcvdt.fifo)) {
+               long current_state = current->state;
+               DECLARE_WAITQUEUE(wait, current);
+
+               set_current_state(TASK_INTERRUPTIBLE);
+               add_wait_queue(&dev->read_wait_q, &wait);
+               if (fifo_empty(&dev->task->rcvdt.fifo)) {       /* last check */
+                       devstate_unlock(dev);
+                       have_devstate_lock = 0;
+                       schedule();
+               }
+               set_current_state(current_state);
+               remove_wait_queue(&dev->read_wait_q, &wait);
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               if (!have_devstate_lock) {
+                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto up_out;
+                       }
+                       have_devstate_lock = 1;
+               }
+               if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
+                       goto up_out;
+       }
+
+       ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
+
+up_out:
+       if (have_devstate_lock)
+               devstate_unlock(dev);
+       up(&dev->read_sem);
+       return ret;
+}
+
+static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
+                                   loff_t *ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       struct rcvdt_bk_struct *rcvdt;
+       int have_devstate_lock = 0;
+       ssize_t ret = 0;
+
+       if (count == 0) {
+               return 0;
+       } else if (count & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: odd count is illegal for DSP task device.\n");
+               return -EINVAL;
+       } else if ((int)buf & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: buf should be word aligned for "
+                      "dsp_task_read().\n");
+               return -EINVAL;
+       }
+
+       if (down_tasksem_interruptible(dev, &dev->read_sem))
+               return -ERESTARTSYS;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       have_devstate_lock = 1;
+
+       if (ipblink_empty(&dev->task->rcvdt.bk.link)) {
+               long current_state;
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue(&dev->read_wait_q, &wait);
+               current_state = current->state;
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (ipblink_empty(&dev->task->rcvdt.bk.link)) { /* last check */
+                       devstate_unlock(dev);
+                       have_devstate_lock = 0;
+                       schedule();
+               }
+               set_current_state(current_state);
+               remove_wait_queue(&dev->read_wait_q, &wait);
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               if (!have_devstate_lock) {
+                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto up_out;
+                       }
+                       have_devstate_lock = 1;
+               }
+               /* signal or 0-byte send from DSP */
+               if (ipblink_empty(&dev->task->rcvdt.bk.link))
+                       goto up_out;
+       }
+
+       rcvdt = &dev->task->rcvdt.bk;
+       /* copy from delayed IPBUF */
+       if (sndtyp_pvt(dev->task->ttyp)) {
+               /* private */
+               if (!ipblink_empty(&rcvdt->link)) {
+                       struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+                       unsigned char *base, *src;
+                       size_t bkcnt;
+
+                       if (dsp_mem_enable(ipbp) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto up_out;
+                       }
+                       base = MKVIRT(ipbp->ah, ipbp->al);
+                       bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
+                       if (dsp_address_validate(base, bkcnt,
+                                                "task %s read buffer",
+                                                dev->task->name) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto pv_out1;
+                       }
+                       if (dsp_mem_enable(base) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto pv_out1;
+                       }
+                       src = base + rcvdt->rp;
+                       if (bkcnt > count) {
+                               if (copy_to_user_dsp(buf, src, count)) {
+                                       ret = -EFAULT;
+                                       goto pv_out2;
+                               }
+                               ret = count;
+                               rcvdt->rp += count;
+                       } else {
+                               if (copy_to_user_dsp(buf, src, bkcnt)) {
+                                       ret = -EFAULT;
+                                       goto pv_out2;
+                               }
+                               ret = bkcnt;
+                               spin_lock(&rcvdt->link.lock);
+                               ipblink_del_pvt(&rcvdt->link);
+                               spin_unlock(&rcvdt->link.lock);
+                               release_ipbuf_pvt(ipbp);
+                               rcvdt->rp = 0;
+                       }
+pv_out2:
+                       dsp_mem_disable(src);
+pv_out1:
+                       dsp_mem_disable(ipbp);
+               }
+       } else {
+               /* global */
+               if (dsp_mem_enable_ipbuf() < 0) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               while (!ipblink_empty(&rcvdt->link)) {
+                       unsigned char *src;
+                       size_t bkcnt;
+                       unsigned short bid = rcvdt->link.top;
+                       struct ipbuf *ipbp = ipbuf[bid];
+
+                       src = ipbp->d + rcvdt->rp;
+                       bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
+                       if (bkcnt > count) {
+                               if (copy_to_user_dsp(buf, src, count)) {
+                                       ret = -EFAULT;
+                                       goto gb_out;
+                               }
+                               ret += count;
+                               rcvdt->rp += count;
+                               break;
+                       } else {
+                               if (copy_to_user_dsp(buf, src, bkcnt)) {
+                                       ret = -EFAULT;
+                                       goto gb_out;
+                               }
+                               ret += bkcnt;
+                               buf += bkcnt;
+                               count -= bkcnt;
+                               spin_lock(&rcvdt->link.lock);
+                               ipblink_del_top(&rcvdt->link, ipbuf);
+                               spin_unlock(&rcvdt->link.lock);
+                               unuse_ipbuf(bid);
+                               rcvdt->rp = 0;
+                       }
+               }
+gb_out:
+               dsp_mem_disable_ipbuf();
+       }
+
+up_out:
+       if (have_devstate_lock)
+               devstate_unlock(dev);
+       up(&dev->read_sem);
+       return ret;
+}
+
+static ssize_t dsp_task_read_wd_psv(struct file *file, char *buf, size_t count,
+                                   loff_t *ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       struct mbcmd mb;
+       unsigned char tid;
+       int ret = 0;
+
+       if (count == 0) {
+               return 0;
+       } else if (count & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: odd count is illegal for DSP task device.\n");
+               return -EINVAL;
+       } else {
+               /* force! */
+               count = 2;
+       }
+
+       if (down_tasksem_interruptible(dev, &dev->read_sem))
+               return -ERESTARTSYS;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       tid = dev->task->tid;
+       devstate_unlock(dev);
+
+       mbcmd_set(mb, MBCMD(WDREQ), tid, 0);
+       dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
+
+       if (signal_pending(current)) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
+               goto unlock_out;
+
+       ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
+
+unlock_out:
+       devstate_unlock(dev);
+up_out:
+       up(&dev->read_sem);
+       return ret;
+}
+
+static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
+                                   loff_t *ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       struct rcvdt_bk_struct *rcvdt;
+       struct mbcmd mb;
+       unsigned char tid;
+       int ret = 0;
+
+       if (count == 0) {
+               return 0;
+       } else if (count & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: odd count is illegal for DSP task device.\n");
+               return -EINVAL;
+       } else if ((int)buf & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: buf should be word aligned for "
+                      "dsp_task_read().\n");
+               return -EINVAL;
+       }
+
+       if (down_tasksem_interruptible(dev, &dev->read_sem))
+               return -ERESTARTSYS;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       tid = dev->task->tid;
+       devstate_unlock(dev);
+
+       mbcmd_set(mb, MBCMD(BKREQ), tid, count/2);
+       dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
+
+       if (signal_pending(current)) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       rcvdt = &dev->task->rcvdt.bk;
+       /* signal or 0-byte send from DSP */
+       if (ipblink_empty(&rcvdt->link))
+               goto unlock_out;
+
+       /*
+        * We will not receive more than requested count.
+        */
+       if (sndtyp_pvt(dev->task->ttyp)) {
+               /* private */
+               struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+               size_t rcvcnt;
+               void *src;
+
+               if (dsp_mem_enable(ipbp) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto unlock_out;
+               }
+               src = MKVIRT(ipbp->ah, ipbp->al);
+               rcvcnt = ((unsigned long)ipbp->c) * 2;
+               if (dsp_address_validate(src, rcvcnt, "task %s read buffer",
+                                        dev->task->name) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto pv_out1;
+               }
+               if (dsp_mem_enable(src) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto pv_out1;
+               }
+               if (count > rcvcnt)
+                       count = rcvcnt;
+               if (copy_to_user_dsp(buf, src, count)) {
+                       ret = -EFAULT;
+                       goto pv_out2;
+               }
+               spin_lock(&rcvdt->link.lock);
+               ipblink_del_pvt(&rcvdt->link);
+               spin_unlock(&rcvdt->link.lock);
+               release_ipbuf_pvt(ipbp);
+               ret = count;
+pv_out2:
+               dsp_mem_disable(src);
+pv_out1:
+               dsp_mem_disable(ipbp);
+       } else {
+               /* global */
+               unsigned short bid = rcvdt->link.top;
+               struct ipbuf *ipbp = ipbuf[bid];
+               size_t rcvcnt;
+
+               if (dsp_mem_enable_ipbuf() < 0) {
+                       ret = -ERESTARTSYS;
+                       goto unlock_out;
+               }
+               rcvcnt = ((unsigned long)ipbp->c) * 2;
+               if (count > rcvcnt)
+                       count = rcvcnt;
+               if (copy_to_user_dsp(buf, ipbp->d, count)) {
+                       ret = -EFAULT;
+                       goto gb_out;
+               }
+               spin_lock(&rcvdt->link.lock);
+               ipblink_del_top(&rcvdt->link, ipbuf);
+               spin_unlock(&rcvdt->link.lock);
+               unuse_ipbuf(bid);
+               ret = count;
+gb_out:
+               dsp_mem_disable_ipbuf();
+       }
+
+unlock_out:
+       devstate_unlock(dev);
+up_out:
+       up(&dev->read_sem);
+       return ret;
+}
+
+static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
+                                size_t count, loff_t *ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       unsigned short wd;
+       int have_devstate_lock = 0;
+       int ret = 0;
+
+       if (count == 0) {
+               return 0;
+       } else if (count & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: odd count is illegal for DSP task device.\n");
+               return -EINVAL;
+       } else {
+               /* force! */
+               count = 2;
+       }
+
+       if (down_tasksem_interruptible(dev, &dev->write_sem))
+               return -ERESTARTSYS;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       have_devstate_lock = 1;
+
+       if (dev->task->wsz == 0) {
+               long current_state;
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue(&dev->write_wait_q, &wait);
+               current_state = current->state;
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (dev->task->wsz == 0) {      /* last check */
+                       devstate_unlock(dev);
+                       have_devstate_lock = 0;
+                       schedule();
+               }
+               set_current_state(current_state);
+               remove_wait_queue(&dev->write_wait_q, &wait);
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               if (!have_devstate_lock) {
+                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto up_out;
+                       }
+                       have_devstate_lock = 1;
+               }
+               if (dev->task->wsz == 0)        /* should not occur */
+                       goto up_out;
+       }
+
+       if (copy_from_user(&wd, buf, count)) {
+               ret = -EFAULT;
+               goto up_out;
+       }
+
+       spin_lock(&dev->task->wsz_lock);
+       if (dsp_mbsend(MBCMD(WDSND), dev->task->tid, wd) < 0) {
+               spin_unlock(&dev->task->wsz_lock);
+               goto up_out;
+       }
+       ret = count;
+       if (rcvtyp_acv(dev->task->ttyp))
+               dev->task->wsz = 0;
+       spin_unlock(&dev->task->wsz_lock);
+
+up_out:
+       if (have_devstate_lock)
+               devstate_unlock(dev);
+       up(&dev->write_sem);
+       return ret;
+}
+
+static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
+                                size_t count, loff_t *ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       int have_devstate_lock = 0;
+       int ret = 0;
+
+       if (count == 0) {
+               return 0;
+       } else if (count & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: odd count is illegal for DSP task device.\n");
+               return -EINVAL;
+       } else if ((int)buf & 0x1) {
+               printk(KERN_ERR
+                      "omapdsp: buf should be word aligned for "
+                      "dsp_task_write().\n");
+               return -EINVAL;
+       }
+
+       if (down_tasksem_interruptible(dev, &dev->write_sem))
+               return -ERESTARTSYS;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+       have_devstate_lock = 1;
+
+       if (dev->task->wsz == 0) {
+               long current_state;
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue(&dev->write_wait_q, &wait);
+               current_state = current->state;
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (dev->task->wsz == 0) {      /* last check */
+                       devstate_unlock(dev);
+                       have_devstate_lock = 0;
+                       schedule();
+               }
+               set_current_state(current_state);
+               remove_wait_queue(&dev->write_wait_q, &wait);
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               if (!have_devstate_lock) {
+                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto up_out;
+                       }
+                       have_devstate_lock = 1;
+               }
+               if (dev->task->wsz == 0)        /* should not occur */
+                       goto up_out;
+       }
+
+       if (count > dev->task->wsz)
+               count = dev->task->wsz;
+
+       if (rcvtyp_pvt(dev->task->ttyp)) {
+               /* private */
+               struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_w;
+               unsigned char *dst;
+
+               if (dsp_mem_enable(ipbp) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               dst = MKVIRT(ipbp->ah, ipbp->al);
+               if (dsp_address_validate(dst, count, "task %s write buffer",
+                                        dev->task->name) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto pv_out1;
+               }
+               if (dsp_mem_enable(dst) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto pv_out1;
+               }
+               if (copy_from_user_dsp(dst, buf, count)) {
+                       ret = -EFAULT;
+                       goto pv_out2;
+               }
+               ipbp->c = count/2;
+               ipbp->s = dev->task->tid;
+               spin_lock(&dev->task->wsz_lock);
+               if (dsp_mbsend(MBCMD(BKSNDP), dev->task->tid, 0) == 0) {
+                       if (rcvtyp_acv(dev->task->ttyp))
+                               dev->task->wsz = 0;
+                       ret = count;
+               }
+               spin_unlock(&dev->task->wsz_lock);
+pv_out2:
+               dsp_mem_disable(dst);
+pv_out1:
+               dsp_mem_disable(ipbp);
+       } else {
+               /* global */
+               struct ipbuf *ipbp;
+               unsigned short bid;
+
+               if (dsp_mem_enable_ipbuf() < 0) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               bid = get_free_ipbuf(dev->task->tid);
+               if (bid == OMAP_DSP_BID_NULL)
+                       goto gb_out;
+               ipbp = ipbuf[bid];
+               if (copy_from_user_dsp(ipbp->d, buf, count)) {
+                       release_ipbuf(bid);
+                       ret = -EFAULT;
+                       goto gb_out;
+               }
+               ipbp->c  = count/2;
+               ipbp->sa = dev->task->tid;
+               spin_lock(&dev->task->wsz_lock);
+               if (dsp_mbsend(MBCMD(BKSND), dev->task->tid, bid) == 0) {
+                       if (rcvtyp_acv(dev->task->ttyp))
+                               dev->task->wsz = 0;
+                       ret = count;
+                       ipb_bsycnt_inc(&ipbcfg);
+               } else
+                       release_ipbuf(bid);
+               spin_unlock(&dev->task->wsz_lock);
+gb_out:
+               dsp_mem_disable_ipbuf();
+       }
+
+up_out:
+       if (have_devstate_lock)
+               devstate_unlock(dev);
+       up(&dev->write_sem);
+       return ret;
+}
+
+static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       struct dsptask *task = dev->task;
+       unsigned int mask = 0;
+
+       poll_wait(file, &dev->read_wait_q, wait);
+       poll_wait(file, &dev->write_wait_q, wait);
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
+               return 0;
+       if (sndtyp_psv(task->ttyp) ||
+           (sndtyp_wd(task->ttyp) && !fifo_empty(&task->rcvdt.fifo)) ||
+           (sndtyp_bk(task->ttyp) && !ipblink_empty(&task->rcvdt.bk.link)))
+               mask |= POLLIN | POLLRDNORM;
+       if (task->wsz)
+               mask |= POLLOUT | POLLWRNORM;
+       devstate_unlock(dev);
+
+       return mask;
+}
+
+static int dsp_task_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       unsigned int minor = MINOR(inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       struct mbcmd mb;
+       unsigned char tid;
+       struct mb_exarg mbarg, *mbargp;
+       int mbargc;
+       unsigned short mbargv[1];
+       int interactive;
+       int ret;
+
+       /* LOCK / UNLOCK operations */
+       switch (cmd) {
+       case OMAP_DSP_TASK_IOCTL_LOCK:
+               return taskdev_lock(dev);
+       case OMAP_DSP_TASK_IOCTL_UNLOCK:
+               return taskdev_unlock(dev);
+       }
+
+       /*
+        * actually only interractive commands need to lock
+        * the semaphore, but here all commands do it for simplicity.
+        */
+       if (down_tasksem_interruptible(dev, &dev->ioctl_sem))
+               return -ERESTARTSYS;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+               ret = -ERESTARTSYS;
+               goto up_out;
+       }
+
+       if ((cmd >= 0x0080) && (cmd < 0x0100)) {
+               /*
+                * 0x0080 - 0x00ff
+                * reserved for backward compatibility
+                * user-defined TCTL commands: no arg, non-interactive
+                */
+               printk(KERN_WARNING "omapdsp: "
+                      "TCTL commands in 0x0080 - 0x0100 are obsolete.\n"
+                      "they won't be supported in the future.\n");
+               mbargc = 0;
+               interactive = 0;
+       } else if (cmd < 0x8000) {
+               /*
+                * 0x0000 - 0x7fff (except 0x0080 - 0x00ff)
+                * system reserved TCTL commands
+                */
+               switch (cmd) {
+               case OMAP_DSP_MBCMD_TCTL_TEN:
+               case OMAP_DSP_MBCMD_TCTL_TDIS:
+                       mbargc = 0;
+                       interactive = 0;
+                       break;
+               default:
+                       ret = -ENOIOCTLCMD;
+                       goto unlock_out;
+               }
+       }
+       /*
+        * 0x8000 - 0xffff
+        * user-defined TCTL commands
+        */
+       else if (cmd < 0x8100) {
+               /* 0x8000-0x80ff: no arg, non-interactive */
+               mbargc = 0;
+               interactive = 0;
+       } else if (cmd < 0x8200) {
+               /* 0x8100-0x81ff: 1 arg, non-interactive */
+               mbargc = 1;
+               mbargv[0] = arg & 0xffff;
+               interactive = 0;
+       } else if (cmd < 0x9000) {
+               /* 0x8200-0x8fff: reserved */
+               ret = -ENOIOCTLCMD;
+               goto unlock_out;
+       } else if (cmd < 0x9100) {
+               /* 0x9000-0x90ff: no arg, interactive */
+               mbargc = 0;
+               interactive = 1;
+       } else if (cmd < 0x9200) {
+               /* 0x9100-0x91ff: 1 arg, interactive */
+               mbargc = 1;
+               mbargv[0] = arg & 0xffff;
+               interactive = 1;
+       } else if (cmd < 0x10000) {
+               /* 0x9200-0xffff: reserved */
+               ret =  -ENOIOCTLCMD;
+               goto unlock_out;
+       } else {
+               /*
+                * 0x10000 -
+                * non TCTL ioctls
+                */
+               switch (cmd) {
+               case OMAP_DSP_TASK_IOCTL_BFLSH:
+                       ret = dsp_task_flush_buf(dev->task);
+                       break;
+               case OMAP_DSP_TASK_IOCTL_SETBSZ:
+                       ret = dsp_task_set_fifosz(dev->task, arg);
+                       break;
+               case OMAP_DSP_TASK_IOCTL_GETNAME:
+                       ret = 0;
+                       if (copy_to_user((void *)arg, dev->name,
+                                        strlen(dev->name) + 1))
+                               ret = -EFAULT;
+                       break;
+               default:
+                       ret = -ENOIOCTLCMD;
+               }
+               goto unlock_out;
+       }
+
+       /*
+        * issue TCTL
+        */
+       tid = dev->task->tid;
+       mbcmd_set(mb, MBCMD(TCTL), tid, cmd);
+       if (mbargc > 0) {
+               mbarg.argc = mbargc;
+               mbarg.tid  = tid;
+               mbarg.argv = mbargv;
+               mbargp = &mbarg;
+       } else
+               mbargp = NULL;
+
+       if (interactive) {
+               dev->task->tctl_stat = -ERESTARTSYS;
+               devstate_unlock(dev);
+
+               dsp_mbcmd_send_and_wait_exarg(&mb, mbargp, &dev->ioctl_wait_q);
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto up_out;
+               }
+               ret = dev->task->tctl_stat;
+               if (ret < 0) {
+                       printk(KERN_ERR "omapdsp: TCTL not responding.\n");
+                       goto unlock_out;
+               }
+       } else {
+               dsp_mbcmd_send_exarg(&mb, mbargp);
+               ret = 0;
+       }
+
+unlock_out:
+       devstate_unlock(dev);
+up_out:
+       up(&dev->ioctl_sem);
+       return ret;
+}
+
+static void dsp_task_mmap_open(struct vm_area_struct *vma)
+{
+       struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
+       struct dsptask *task;
+       size_t len = vma->vm_end - vma->vm_start;
+
+       BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+       task = dev->task;
+       exmap_use(task->map_base, len);
+}
+
+static void dsp_task_mmap_close(struct vm_area_struct *vma)
+{
+       struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
+       struct dsptask *task;
+       size_t len = vma->vm_end - vma->vm_start;
+
+       BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+       task = dev->task;
+       exmap_unuse(task->map_base, len);
+}
+
+/**
+ * On demand page allocation is not allowed. The mapping area is defined by
+ * corresponding DSP tasks.
+ */
+static struct page *dsp_task_mmap_nopage(struct vm_area_struct *vma,
+                                        unsigned long address, int *type)
+{
+       return NOPAGE_SIGBUS;
+}
+
+static struct vm_operations_struct dsp_task_vm_ops = {
+       .open = dsp_task_mmap_open,
+       .close = dsp_task_mmap_close,
+       .nopage = dsp_task_mmap_nopage,
+};
+
+static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       void *tmp_vadr;
+       unsigned long tmp_padr, tmp_vmadr, off;
+       size_t req_len, tmp_len;
+       unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       struct dsptask *task;
+       int ret = 0;
+
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
+               return -ERESTARTSYS;
+       task = dev->task;
+
+       /*
+        * Don't swap this area out
+        * Don't dump this area to a core file
+        */
+       vma->vm_flags |= VM_RESERVED | VM_IO;
+
+       /* Do not cache this area */
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       req_len = vma->vm_end - vma->vm_start;
+       off = vma->vm_pgoff << PAGE_SHIFT;
+       tmp_vmadr = vma->vm_start;
+       tmp_vadr = task->map_base + off;
+       do {
+               tmp_padr = dsp_virt_to_phys(tmp_vadr, &tmp_len);
+               if (tmp_padr == 0) {
+                       printk(KERN_ERR
+                              "omapdsp: task %s: illegal address "
+                              "for mmap: %p", task->name, tmp_vadr);
+                       /* partial mapping will be cleared in upper layer */
+                       ret = -EINVAL;
+                       goto unlock_out;
+               }
+               if (tmp_len > req_len)
+                       tmp_len = req_len;
+
+               printk(KERN_DEBUG
+                      "omapdsp: mmap info: "
+                      "vmadr = %08lx, padr = %08lx, len = %x\n",
+                      tmp_vmadr, tmp_padr, tmp_len);
+               if (remap_pfn_range(vma, tmp_vmadr, tmp_padr >> PAGE_SHIFT,
+                                   tmp_len, vma->vm_page_prot) != 0) {
+                       printk(KERN_ERR
+                              "omapdsp: task %s: remap_page_range() failed.\n",
+                              task->name);
+                       /* partial mapping will be cleared in upper layer */
+                       ret = -EINVAL;
+                       goto unlock_out;
+               }
+
+               req_len   -= tmp_len;
+               tmp_vmadr += tmp_len;
+               tmp_vadr  += tmp_len;
+       } while (req_len);
+
+       vma->vm_ops = &dsp_task_vm_ops;
+       vma->vm_private_data = dev;
+       exmap_use(task->map_base, vma->vm_end - vma->vm_start);
+
+unlock_out:
+       devstate_unlock(dev);
+       return ret;
+}
+
+static int dsp_task_open(struct inode *inode, struct file *file)
+{
+       unsigned int minor = MINOR(inode->i_rdev);
+       struct taskdev *dev;
+       int ret = 0;
+
+       if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL))
+               return -ENODEV;
+       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_NOTASK |
+                              OMAP_DSP_DEVSTATE_ATTACHED) < 0)
+               return -ERESTARTSYS;
+#ifndef CONFIG_OMAP_DSP_TASK_MULTIOPEN
+       if (dev->usecount > 0) {
+               ret = -EBUSY;
+               goto unlock_out;
+       }
+#endif
+
+       if (dev->state & OMAP_DSP_DEVSTATE_NOTASK) {
+               dev->state = OMAP_DSP_DEVSTATE_ADDREQ;
+               /* wake up twch daemon for tadd */
+               dsp_twch_touch();
+               devstate_unlock(dev);
+               if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED |
+                                      OMAP_DSP_DEVSTATE_ADDFAIL) < 0) {
+                       spin_lock(&dev->state_lock);
+                       if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ)
+                               dev->state = OMAP_DSP_DEVSTATE_NOTASK;
+                       spin_unlock(&dev->state_lock);
+                       return -ERESTARTSYS;
+               }
+               if (dev->state & OMAP_DSP_DEVSTATE_ADDFAIL) {
+                       printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
+                              dev->name);
+                       ret = -EBUSY;
+                       dev->state = OMAP_DSP_DEVSTATE_NOTASK;
+                       wake_up_interruptible_all(&dev->state_wait_q);
+                       goto unlock_out;
+               }
+       }
+
+       /* state_lock covers usecount, proc_list as well. */
+       dev->usecount++;
+       proc_list_add(&dev->proc_list, current);
+       file->f_op = &dev->fops;
+       devstate_unlock(dev);
+
+       return 0;
+
+unlock_out:
+       devstate_unlock(dev);
+       return ret;
+}
+
+static int dsp_task_release(struct inode *inode, struct file *file)
+{
+       unsigned int minor = MINOR(inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+
+       /* state_lock covers usecount, proc_list as well. */
+       spin_lock(&dev->state_lock);
+
+       /* state can be ATTACHED, KILLING or GARBAGE here. */
+       switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
+
+       case OMAP_DSP_DEVSTATE_KILLING:
+               dev->usecount--;
+               break;
+
+       case OMAP_DSP_DEVSTATE_GARBAGE:
+               if(--dev->usecount == 0) {
+                       dev->state = OMAP_DSP_DEVSTATE_NOTASK;
+                       wake_up_interruptible_all(&dev->state_wait_q);
+               }
+               break;
+
+       case OMAP_DSP_DEVSTATE_ATTACHED:
+               if (dev->lock_pid == current->pid)
+                       taskdev_unlock(dev);
+               proc_list_del(&dev->proc_list, current);
+               if (--dev->usecount == 0) {
+                       if (minor >= n_task) {  /* dynamic task */
+                               dev->state = OMAP_DSP_DEVSTATE_DELREQ;
+                               /* wake up twch daemon for tdel */
+                               dsp_twch_touch();
+                       }
+               }
+               break;
+
+       }
+
+       spin_unlock(&dev->state_lock);
+       return 0;
+}
+
+/*
+ * mkdev / rmdev
+ */
+int dsp_mkdev(char *name)
+{
+       struct taskdev *dev;
+       int status;
+       unsigned char minor;
+
+       if (!dsp_is_ready()) {
+               printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
+               return -EINVAL;
+       }
+       for (minor = n_task; minor < TASKDEV_MAX; minor++) {
+               if (taskdev[minor] == NULL)
+                       goto do_make;
+       }
+       printk(KERN_ERR "omapdsp: Too many task devices.\n");
+       return -EBUSY;
+
+do_make:
+       if ((dev = kmalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL)
+               return -ENOMEM;
+       memset(dev, 0, sizeof(struct taskdev));
+       if ((status = taskdev_init(dev, name, minor)) < 0) {
+               kfree(dev);
+               return status;
+       }
+       return minor;
+}
+
+int dsp_rmdev(char *name)
+{
+       unsigned char minor;
+       int ret;
+
+       if (!dsp_is_ready()) {
+               printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
+               return -EINVAL;
+       }
+       for (minor = n_task; minor < TASKDEV_MAX; minor++) {
+               if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
+                       if ((ret = dsp_rmdev_minor(minor)) < 0)
+                               return ret;
+                       return minor;
+               }
+       }
+       return -EINVAL;
+}
+
+static int dsp_rmdev_minor(unsigned char minor)
+{
+       struct taskdev *dev = taskdev[minor];
+
+       spin_lock(&dev->state_lock);
+
+       switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
+
+       case OMAP_DSP_DEVSTATE_NOTASK:
+               /* fine */
+               break;
+
+       case OMAP_DSP_DEVSTATE_ATTACHED:
+               /* task is working. kill it. */
+               {
+                       siginfo_t info;
+                       struct proc_list *pl;
+
+                       dev->state = OMAP_DSP_DEVSTATE_KILLING;
+                       info.si_signo = SIGBUS;
+                       info.si_errno = 0;
+                       info.si_code = SI_KERNEL;
+                       info._sifields._sigfault._addr = NULL;
+                       list_for_each_entry(pl, &dev->proc_list, list_head) {
+                               send_sig_info(SIGBUS, &info, pl->tsk);
+                       }
+                       spin_unlock(&dev->state_lock);
+                       dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+                       goto invalidate;
+               }
+
+       case OMAP_DSP_DEVSTATE_ADDREQ:
+               /* open() is waiting. drain it. */
+               dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
+               wake_up_interruptible_all(&dev->state_wait_q);
+               break;
+
+       case OMAP_DSP_DEVSTATE_DELREQ:
+               /* nobody is waiting. */
+               dev->state = OMAP_DSP_DEVSTATE_NOTASK;
+               wake_up_interruptible_all(&dev->state_wait_q);
+               break;
+
+       case OMAP_DSP_DEVSTATE_ADDING:
+       case OMAP_DSP_DEVSTATE_DELING:
+       case OMAP_DSP_DEVSTATE_KILLING:
+       case OMAP_DSP_DEVSTATE_GARBAGE:
+       case OMAP_DSP_DEVSTATE_ADDFAIL:
+               /* transient state. wait for a moment. */
+               break;
+
+       }
+
+       spin_unlock(&dev->state_lock);
+
+invalidate:
+       /* wait for some time and hope the state is settled */
+       devstate_lock_timeout(dev, OMAP_DSP_DEVSTATE_NOTASK, HZ);
+       if (!(dev->state & OMAP_DSP_DEVSTATE_NOTASK)) {
+               printk(KERN_WARNING
+                      "omapdsp: illegal device state (%s) on rmdev %s.\n",
+                      devstate_name(dev->state), dev->name);
+       }
+       dev->state = OMAP_DSP_DEVSTATE_INVALID;
+       devstate_unlock(dev);
+
+       taskdev_delete(minor);
+       kfree(dev);
+
+       return 0;
+}
+
+struct file_operations dsp_task_fops = {
+       .owner   = THIS_MODULE,
+       .poll    = dsp_task_poll,
+       .ioctl   = dsp_task_ioctl,
+       .open    = dsp_task_open,
+       .release = dsp_task_release,
+};
+
+static void dsptask_dev_release(struct device *dev)
+{
+}
+
+static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
+{
+       struct class_device *cdev;
+
+       taskdev[minor] = dev;
+
+       INIT_LIST_HEAD(&dev->proc_list);
+       init_waitqueue_head(&dev->read_wait_q);
+       init_waitqueue_head(&dev->write_wait_q);
+       init_waitqueue_head(&dev->ioctl_wait_q);
+       init_MUTEX(&dev->read_sem);
+       init_MUTEX(&dev->write_sem);
+       init_MUTEX(&dev->ioctl_sem);
+       init_MUTEX(&dev->lock_sem);
+       dev->lock_pid = 0;
+
+       strncpy(dev->name, name, OMAP_DSP_TNM_LEN);
+       dev->name[OMAP_DSP_TNM_LEN-1] = '\0';
+       dev->state = (minor < n_task) ? OMAP_DSP_DEVSTATE_ATTACHED :
+                                       OMAP_DSP_DEVSTATE_NOTASK;
+       dev->usecount = 0;
+       memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
+
+       dev->dev.parent = &dsp_device.dev;
+       dev->dev.bus = &dsptask_bus;
+       sprintf(dev->dev.bus_id, "dsptask%d", minor);
+       dev->dev.release = dsptask_dev_release;
+       device_register(&dev->dev);
+       device_create_file(&dev->dev, &dev_attr_devname);
+       device_create_file(&dev->dev, &dev_attr_devstate);
+       device_create_file(&dev->dev, &dev_attr_proc_list);
+       cdev = class_device_create(dsp_task_class, NULL,
+                                  MKDEV(OMAP_DSP_TASK_MAJOR, minor),
+                                  NULL, "dsptask%d", minor);
+
+       init_waitqueue_head(&dev->state_wait_q);
+       spin_lock_init(&dev->state_lock);
+
+       return 0;
+}
+
+static void taskdev_delete(unsigned char minor)
+{
+       struct taskdev *dev = taskdev[minor];
+
+       if (!dev)
+               return;
+       device_remove_file(&dev->dev, &dev_attr_devname);
+       device_remove_file(&dev->dev, &dev_attr_devstate);
+       device_remove_file(&dev->dev, &dev_attr_proc_list);
+       class_device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
+       device_unregister(&dev->dev);
+       proc_list_flush(&dev->proc_list);
+       taskdev[minor] = NULL;
+}
+
+static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
+{
+       unsigned short ttyp = task->ttyp;
+
+       dev->task = task;
+       task->dev = dev;
+       dev->fops.read =
+               sndtyp_acv(ttyp) ?
+                       sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
+                       /* sndtyp_bk */   dsp_task_read_bk_acv:
+               /* sndtyp_psv */
+                       sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
+                       /* sndtyp_bk */   dsp_task_read_bk_psv;
+       dev->fops.write =
+               rcvtyp_wd(ttyp) ? dsp_task_write_wd:
+               /* rcvbyp_bk */   dsp_task_write_bk;
+       if (task->map_length)
+               dev->fops.mmap = dsp_task_mmap;
+
+       device_create_file(&dev->dev, &dev_attr_taskname);
+       device_create_file(&dev->dev, &dev_attr_ttyp);
+       if (sndtyp_wd(ttyp)) {
+               device_create_file(&dev->dev, &dev_attr_fifosz);
+               device_create_file(&dev->dev, &dev_attr_fifocnt);
+       } else
+               device_create_file(&dev->dev, &dev_attr_ipblink);
+       device_create_file(&dev->dev, &dev_attr_wsz);
+       if (task->map_length)
+               device_create_file(&dev->dev, &dev_attr_mmap);
+}
+
+static void taskdev_detach_task(struct taskdev *dev)
+{
+       unsigned short ttyp = dev->task->ttyp;
+
+       device_remove_file(&dev->dev, &dev_attr_taskname);
+       device_remove_file(&dev->dev, &dev_attr_ttyp);
+       if (sndtyp_wd(ttyp)) {
+               device_remove_file(&dev->dev, &dev_attr_fifosz);
+               device_remove_file(&dev->dev, &dev_attr_fifocnt);
+       } else
+               device_remove_file(&dev->dev, &dev_attr_ipblink);
+       device_remove_file(&dev->dev, &dev_attr_wsz);
+       if (dev->task->map_length)
+               device_remove_file(&dev->dev, &dev_attr_mmap);
+
+       if (dev->task) {
+               dev->task = NULL;
+               dev->fops.read = NULL;
+               dev->fops.write = NULL;
+               printk(KERN_INFO "omapdsp: taskdev %s disabled.\n", dev->name);
+       }
+}
+
+/*
+ * tadd / tdel / tkill
+ */
+int dsp_tadd(unsigned char minor, unsigned long adr)
+{
+       struct taskdev *dev;
+       struct dsptask *task;
+       struct mbcmd mb;
+       struct mb_exarg arg;
+       unsigned char tid, tid_response;
+       unsigned short argv[2];
+       int ret = minor;
+
+       if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+               printk(KERN_ERR
+                      "omapdsp: no task device with minor %d\n", minor);
+               return -EINVAL;
+       }
+
+       spin_lock(&dev->state_lock);
+       if (!(dev->state & OMAP_DSP_DEVSTATE_ADDREQ)) {
+               printk(KERN_ERR
+                      "omapdsp: taskdev %s is not requesting for tadd. "
+                      "(state is %s)\n", dev->name, devstate_name(dev->state));
+               spin_unlock(&dev->state_lock);
+               return -EINVAL;
+       }
+       dev->state = OMAP_DSP_DEVSTATE_ADDING;
+       spin_unlock(&dev->state_lock);
+
+       if (adr == OMAP_DSP_TADD_ABORTADR) {
+               /* aborting tadd intentionally */
+               printk(KERN_INFO "omapdsp: tadd address is ABORTADR.\n");
+               goto fail_out;
+       }
+       if (adr >= DSPSPACE_SIZE) {
+               printk(KERN_ERR
+                      "omapdsp: illegal address 0x%08lx for tadd\n", adr);
+               ret = -EINVAL;
+               goto fail_out;
+       }
+
+       adr >>= 1;      /* word address */
+       argv[0] = adr >> 16;    /* addrh */
+       argv[1] = adr & 0xffff; /* addrl */
+
+       if (down_interruptible(&cfg_sem)) {
+               ret = -ERESTARTSYS;
+               goto fail_out;
+       }
+       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_cmd = MBCMD(TADD);
+       mbcmd_set(mb, MBCMD(TADD), 0, 0);
+       arg.tid  = OMAP_DSP_TID_ANON;
+       arg.argc = 2;
+       arg.argv = argv;
+
+       dsp_mem_sync_inc();
+       dsp_mbcmd_send_and_wait_exarg(&mb, &arg, &cfg_wait_q);
+
+       tid = cfg_tid;
+       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_cmd = 0;
+       up(&cfg_sem);
+
+       if (tid == OMAP_DSP_TID_ANON) {
+               printk(KERN_ERR "omapdsp: tadd failed!\n");
+               ret = -EINVAL;
+               goto fail_out;
+       }
+       if ((tid < n_task) || dsptask[tid]) {
+               printk(KERN_ERR "omapdsp: illegal tid (%d)!\n", tid);
+               ret = -EINVAL;
+               goto fail_out;
+       }
+       if ((task = kmalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
+               ret = -ENOMEM;
+               goto del_out;
+       }
+       memset(task, 0, sizeof(struct dsptask));
+
+       if ((ret = dsp_task_config(task, tid)) < 0)
+               goto free_out;
+       taskdev_attach_task(dev, task);
+
+       if (strcmp(dev->name, task->name)) {
+               printk(KERN_ERR
+                      "omapdsp: task name (%s) doesn't match with "
+                      "device name (%s).\n", task->name, dev->name);
+               ret = -EINVAL;
+               goto free_out;
+       }
+
+       dsp_task_init(task);
+       printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
+       dev->state = OMAP_DSP_DEVSTATE_ATTACHED;
+       wake_up_interruptible_all(&dev->state_wait_q);
+       return minor;
+
+free_out:
+       kfree(task);
+
+del_out:
+       printk(KERN_ERR "omapdsp: deleting the task...\n");
+
+       dev->state = OMAP_DSP_DEVSTATE_DELING;
+
+       if (down_interruptible(&cfg_sem)) {
+               printk(KERN_ERR "omapdsp: aborting tdel process. "
+                               "DSP side could be corrupted.\n");
+               goto fail_out;
+       }
+       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_cmd = MBCMD(TDEL);
+       mbcmd_set(mb, MBCMD(TDEL), tid, OMAP_DSP_MBCMD_TDEL_KILL);
+       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+       tid_response = cfg_tid;
+       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_cmd = 0;
+       up(&cfg_sem);
+
+       if (tid_response != tid)
+               printk(KERN_ERR "omapdsp: tdel failed. "
+                               "DSP side could be corrupted.\n");
+
+fail_out:
+       dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
+       wake_up_interruptible_all(&dev->state_wait_q);
+       return ret;
+}
+
+int dsp_tdel(unsigned char minor)
+{
+       struct taskdev *dev;
+
+       if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+               printk(KERN_ERR
+                      "omapdsp: no task device with minor %d\n", minor);
+               return -EINVAL;
+       }
+       spin_lock(&dev->state_lock);
+       if (!(dev->state & OMAP_DSP_DEVSTATE_DELREQ)) {
+               printk(KERN_ERR
+                      "omapdsp: taskdev %s is not requesting for tdel. "
+                      "(state is %s)\n", dev->name, devstate_name(dev->state));
+               spin_unlock(&dev->state_lock);
+               return -EINVAL;
+       }
+       dev->state = OMAP_DSP_DEVSTATE_DELING;
+       spin_unlock(&dev->state_lock);
+
+       return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_SAFE);
+}
+
+int dsp_tkill(unsigned char minor)
+{
+       struct taskdev *dev;
+       siginfo_t info;
+       struct proc_list *pl;
+
+       if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+               printk(KERN_ERR
+                      "omapdsp: no task device with minor %d\n", minor);
+               return -EINVAL;
+       }
+       spin_lock(&dev->state_lock);
+       if (!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED)) {
+               printk(KERN_ERR
+                      "omapdsp: task has not been attached for taskdev %s\n",
+                      dev->name);
+               spin_unlock(&dev->state_lock);
+               return -EINVAL;
+       }
+       dev->state = OMAP_DSP_DEVSTATE_KILLING;
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = SI_KERNEL;
+       info._sifields._sigfault._addr = NULL;
+       list_for_each_entry(pl, &dev->proc_list, list_head) {
+               send_sig_info(SIGBUS, &info, pl->tsk);
+       }
+       spin_unlock(&dev->state_lock);
+
+       return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+}
+
+static int dsp_tdel_bh(unsigned char minor, unsigned short type)
+{
+       struct taskdev *dev = taskdev[minor];
+       struct dsptask *task;
+       struct mbcmd mb;
+       unsigned char tid, tid_response;
+       int ret = minor;
+
+       task = dev->task;
+       tid = task->tid;
+       if (down_interruptible(&cfg_sem)) {
+               if (type == OMAP_DSP_MBCMD_TDEL_SAFE) {
+                       dev->state = OMAP_DSP_DEVSTATE_DELREQ;
+                       return -ERESTARTSYS;
+               } else {
+                       tid_response = OMAP_DSP_TID_ANON;
+                       ret = -ERESTARTSYS;
+                       goto detach_out;
+               }
+       }
+       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_cmd = MBCMD(TDEL);
+       mbcmd_set(mb, MBCMD(TDEL), tid, type);
+       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+       tid_response = cfg_tid;
+       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_cmd = 0;
+       up(&cfg_sem);
+
+detach_out:
+       taskdev_detach_task(dev);
+       dsp_task_unconfig(task);
+       kfree(task);
+
+       if (tid_response != tid) {
+               printk(KERN_ERR "omapdsp: %s failed!\n",
+                      (type == OMAP_DSP_MBCMD_TDEL_SAFE) ? "tdel" : "tkill");
+               ret = -EINVAL;
+       }
+       spin_lock(&dev->state_lock);
+       dev->state = (dev->usecount > 0) ? OMAP_DSP_DEVSTATE_GARBAGE :
+                                          OMAP_DSP_DEVSTATE_NOTASK;
+       wake_up_interruptible_all(&dev->state_wait_q);
+       spin_unlock(&dev->state_lock);
+
+       return ret;
+}
+
+/*
+ * state inquiry
+ */
+long taskdev_state_stale(unsigned char minor)
+{
+       if (taskdev[minor]) {
+               long state = taskdev[minor]->state;
+               taskdev[minor]->state |= OMAP_DSP_DEVSTATE_STALE;
+               return state;
+       } else
+               return OMAP_DSP_DEVSTATE_NOTASK;
+}
+
+/*
+ * functions called from mailbox1 interrupt routine
+ */
+void mbx1_wdsnd(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       struct dsptask *task = dsptask[tid];
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: WDSND with illegal tid! %d\n", tid);
+               return;
+       }
+       if (sndtyp_bk(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: WDSND from block sending task! (task%d)\n", tid);
+               return;
+       }
+       if (sndtyp_psv(task->ttyp) &&
+           !waitqueue_active(&task->dev->read_wait_q)) {
+               printk(KERN_WARNING
+                      "mbx: WDSND from passive sending task (task%d) "
+                      "without request!\n", tid);
+               return;
+       }
+
+       write_word_to_fifo(&task->rcvdt.fifo, mb->data);
+       wake_up_interruptible(&task->dev->read_wait_q);
+}
+
+void mbx1_wdreq(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       struct dsptask *task = dsptask[tid];
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: WDREQ with illegal tid! %d\n", tid);
+               return;
+       }
+       if (rcvtyp_psv(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: WDREQ from passive receiving task! (task%d)\n",
+                      tid);
+               return;
+       }
+
+       spin_lock(&task->wsz_lock);
+       task->wsz = 2;
+       spin_unlock(&task->wsz_lock);
+       wake_up_interruptible(&task->dev->write_wait_q);
+}
+
+void mbx1_bksnd(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       unsigned short bid = mb->data;
+       struct dsptask *task = dsptask[tid];
+       unsigned short cnt;
+
+       if (bid >= ipbcfg.ln) {
+               printk(KERN_ERR "mbx: BKSND with illegal bid! %d\n", bid);
+               return;
+       }
+       ipb_bsycnt_dec(&ipbcfg);
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: BKSND with illegal tid! %d\n", tid);
+               goto unuse_ipbuf_out;
+       }
+       if (sndtyp_wd(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKSND from word sending task! (task%d)\n", tid);
+               goto unuse_ipbuf_out;
+       }
+       if (sndtyp_pvt(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKSND from private sending task! (task%d)\n", tid);
+               goto unuse_ipbuf_out;
+       }
+       if (sync_with_dsp(&ipbuf[bid]->sd, tid, 10) < 0) {
+               printk(KERN_ERR "mbx: BKSND - IPBUF sync failed!\n");
+               return;
+       }
+
+       /* should be done in DSP, but just in case. */
+       ipbuf[bid]->next = OMAP_DSP_BID_NULL;
+
+       cnt = ipbuf[bid]->c;
+       if (cnt > ipbcfg.lsz) {
+               printk(KERN_ERR "mbx: BKSND cnt(%d) > ipbuf line size(%d)!\n",
+                      cnt, ipbcfg.lsz);
+               goto unuse_ipbuf_out;
+       }
+
+       if (cnt == 0) {
+               /* 0-byte send from DSP */
+               unuse_ipbuf_nowait(bid);
+               goto done;
+       }
+       spin_lock(&task->rcvdt.bk.link.lock);
+       ipblink_add_tail(&task->rcvdt.bk.link, bid, ipbuf);
+       spin_unlock(&task->rcvdt.bk.link.lock);
+       /* we keep coming bid and return alternative line to DSP. */
+       balance_ipbuf();
+
+done:
+       wake_up_interruptible(&task->dev->read_wait_q);
+       return;
+
+unuse_ipbuf_out:
+       unuse_ipbuf_nowait(bid);
+       return;
+}
+
+void mbx1_bkreq(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       unsigned short cnt = mb->data;
+       struct dsptask *task = dsptask[tid];
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: BKREQ with illegal tid! %d\n", tid);
+               return;
+       }
+       if (rcvtyp_wd(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKREQ from word receiving task! (task%d)\n", tid);
+               return;
+       }
+       if (rcvtyp_pvt(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKREQ from private receiving task! (task%d)\n",
+                      tid);
+               return;
+       }
+       if (rcvtyp_psv(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKREQ from passive receiving task! (task%d)\n",
+                      tid);
+               return;
+       }
+
+       spin_lock(&task->wsz_lock);
+       task->wsz = cnt*2;
+       spin_unlock(&task->wsz_lock);
+       wake_up_interruptible(&task->dev->write_wait_q);
+}
+
+void mbx1_bkyld(struct mbcmd *mb)
+{
+       unsigned short bid = mb->data;
+
+       if (bid >= ipbcfg.ln) {
+               printk(KERN_ERR "mbx: BKYLD with illegal bid! %d\n", bid);
+               return;
+       }
+
+       /* should be done in DSP, but just in case. */
+       ipbuf[bid]->next = OMAP_DSP_BID_NULL;
+
+       /* we don't need to sync with DSP */
+       ipb_bsycnt_dec(&ipbcfg);
+       release_ipbuf(bid);
+}
+
+void mbx1_bksndp(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       struct dsptask *task = dsptask[tid];
+       struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
+       struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: BKSNDP with illegal tid! %d\n", tid);
+               return;
+       }
+       if (sndtyp_wd(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKSNDP from word sending task! (task%d)\n", tid);
+               return;
+       }
+       if (sndtyp_gbl(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKSNDP from non-private sending task! (task%d)\n",
+                      tid);
+               return;
+       }
+
+       /*
+        * we should not have delayed block at this point
+        * because read() routine releases the lock of the buffer and
+        * until then DSP can't send next data.
+        */
+
+       if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
+               printk(KERN_ERR "mbx: BKSNDP - IPBUF sync failed!\n");
+               return;
+       }
+       printk(KERN_DEBUG "mbx: ipbuf_pvt_r->a = 0x%08lx\n",
+              MKLONG(ipbp->ah, ipbp->al));
+       spin_lock(&rcvdt->link.lock);
+       ipblink_add_pvt(&rcvdt->link);
+       spin_unlock(&rcvdt->link.lock);
+       wake_up_interruptible(&task->dev->read_wait_q);
+}
+
+void mbx1_bkreqp(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       struct dsptask *task = dsptask[tid];
+       struct ipbuf_p *ipbp = task->ipbuf_pvt_w;
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: BKREQP with illegal tid! %d\n", tid);
+               return;
+       }
+       if (rcvtyp_wd(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKREQP from word receiving task! (task%d)\n", tid);
+               return;
+       }
+       if (rcvtyp_gbl(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKREQP from non-private receiving task! (task%d)\n", tid);
+               return;
+       }
+       if (rcvtyp_psv(task->ttyp)) {
+               printk(KERN_ERR
+                      "mbx: BKREQP from passive receiving task! (task%d)\n", tid);
+               return;
+       }
+
+       if (sync_with_dsp(&ipbp->s, OMAP_DSP_TID_FREE, 10) < 0) {
+               printk(KERN_ERR "mbx: BKREQP - IPBUF sync failed!\n");
+               return;
+       }
+       printk(KERN_DEBUG "mbx: ipbuf_pvt_w->a = 0x%08lx\n",
+              MKLONG(ipbp->ah, ipbp->al));
+       spin_lock(&task->wsz_lock);
+       task->wsz = ipbp->c*2;
+       spin_unlock(&task->wsz_lock);
+       wake_up_interruptible(&task->dev->write_wait_q);
+}
+
+void mbx1_tctl(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       struct dsptask *task = dsptask[tid];
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: TCTL with illegal tid! %d\n", tid);
+               return;
+       }
+
+       if (!waitqueue_active(&task->dev->ioctl_wait_q)) {
+               printk(KERN_WARNING "mbx: unexpected TCTL from DSP!\n");
+               return;
+       }
+
+       task->tctl_stat = mb->data;
+       wake_up_interruptible(&task->dev->ioctl_wait_q);
+}
+
+void mbx1_tcfg(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       struct dsptask *task = dsptask[tid];
+       unsigned short *tnm;
+       volatile unsigned short *buf;
+       int i;
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: TCFG with illegal tid! %d\n", tid);
+               return;
+       }
+       if ((task->state != TASK_STATE_CFGREQ) || (cfg_cmd != MBCMD(TCFG))) {
+               printk(KERN_WARNING "mbx: unexpected TCFG from DSP!\n");
+               return;
+       }
+
+       if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
+               printk(KERN_ERR "mbx: TCFG - IPBUF sync failed!\n");
+               goto out;
+       }
+
+       /*
+        * read configuration data on system IPBUF
+        */
+       buf = ipbuf_sys_da->d;
+       task->ttyp                 = buf[0];
+       task->rcvdt.bk.ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
+       task->ipbuf_pvt_w          = MKVIRT(buf[3], buf[4]);
+       task->map_base             = MKVIRT(buf[5], buf[6]);
+       task->map_length           = MKLONG(buf[7], buf[8]) << 1;       /* word -> byte */
+       tnm                        = MKVIRT(buf[9], buf[10]);
+       release_ipbuf_pvt(ipbuf_sys_da);
+
+       /*
+        * copy task name string
+        */
+       if (dsp_address_validate(tnm, OMAP_DSP_TNM_LEN, "task name buffer") <0) {
+               task->name[0] = '\0';
+               goto out;
+       }
+
+       for (i = 0; i < OMAP_DSP_TNM_LEN-1; i++) {
+               /* avoiding byte access */
+               unsigned short tmp = tnm[i];
+               task->name[i] = tmp & 0x00ff;
+               if (!tmp)
+                       break;
+       }
+       task->name[OMAP_DSP_TNM_LEN-1] = '\0';
+
+       task->state = TASK_STATE_READY;
+out:
+       wake_up_interruptible(&cfg_wait_q);
+}
+
+void mbx1_tadd(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+
+       if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TADD))) {
+               printk(KERN_WARNING "mbx: unexpected TADD from DSP!\n");
+               return;
+       }
+       cfg_tid = tid;
+       wake_up_interruptible(&cfg_wait_q);
+}
+
+void mbx1_tdel(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+
+       if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TDEL))) {
+               printk(KERN_WARNING "mbx: unexpected TDEL from DSP!\n");
+               return;
+       }
+       cfg_tid = tid;
+       wake_up_interruptible(&cfg_wait_q);
+}
+
+void mbx1_err_fatal(unsigned char tid)
+{
+       struct dsptask *task = dsptask[tid];
+       struct proc_list *pl;
+       siginfo_t info;
+
+       if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+               printk(KERN_ERR "mbx: FATAL ERR with illegal tid! %d\n", tid);
+               return;
+       }
+
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = SI_KERNEL;
+       info._sifields._sigfault._addr = NULL;
+       spin_lock(&task->dev->state_lock);
+       list_for_each_entry(pl, &task->dev->proc_list, list_head) {
+               send_sig_info(SIGBUS, &info, pl->tsk);
+       }
+       spin_unlock(&task->dev->state_lock);
+}
+
+static short *dbg_buf;
+static unsigned short dbg_buf_sz, dbg_line_sz;
+static int dbg_rp;
+
+int dsp_dbg_config(short *buf, unsigned short sz, unsigned short lsz)
+{
+#ifdef OLD_BINARY_SUPPORT
+       if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
+               dbg_buf = NULL;
+               dbg_buf_sz = 0;
+               dbg_line_sz = 0;
+               dbg_rp = 0;
+               return 0;
+       }
+#endif
+
+       if (dsp_address_validate(buf, sz, "debug buffer") < 0)
+               return -1;
+
+       if (lsz > sz) {
+               printk(KERN_ERR
+                      "omapdsp: dbg_buf lsz (%d) is greater than its "
+                      "buffer size (%d)\n", lsz, sz);
+               return -1;
+       }
+
+       dbg_buf = buf;
+       dbg_buf_sz = sz;
+       dbg_line_sz = lsz;
+       dbg_rp = 0;
+
+       return 0;
+}
+
+void dsp_dbg_stop(void)
+{
+       dbg_buf = NULL;
+}
+
+#ifdef OLD_BINARY_SUPPORT
+static void mbx1_dbg_old(struct mbcmd *mb);
+#endif
+
+void mbx1_dbg(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       int cnt = mb->data;
+       char s[80], *s_end = &s[79], *p;
+       unsigned short *src;
+       int i;
+
+#ifdef OLD_BINARY_SUPPORT
+       if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
+               mbx1_dbg_old(mb);
+               return;
+       }
+#endif
+
+       if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
+           (tid != OMAP_DSP_TID_ANON)) {
+               printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
+               return;
+       }
+       if (dbg_buf == NULL) {
+               printk(KERN_ERR "mbx: DBG command received, but "
+                      "dbg_buf has not been configured yet.\n");
+               return;
+       }
+
+       if (dsp_mem_enable(dbg_buf) < 0)
+               return;
+
+       src = &dbg_buf[dbg_rp];
+       p = s;
+       for (i = 0; i < cnt; i++) {
+               unsigned short tmp;
+               /*
+                * Be carefull that dbg_buf should not be read with
+                * 1-byte access since it might be placed in DARAM/SARAM
+                * and it can cause unexpected byteswap.
+                * For example,
+                *   *(p++) = *(src++) & 0xff;
+                * causes 1-byte access!
+                */
+               tmp = *src++;
+               *(p++) = tmp & 0xff;
+               if (*(p-1) == '\n') {
+                       *p = '\0';
+                       printk(KERN_INFO "%s", s);
+                       p = s;
+                       continue;
+               }
+               if (p == s_end) {
+                       *p = '\0';
+                       printk(KERN_INFO "%s\n", s);
+                       p = s;
+                       continue;
+               }
+       }
+       if (p > s) {
+               *p = '\0';
+               printk(KERN_INFO "%s\n", s);
+       }
+       if ((dbg_rp += cnt + 1) > dbg_buf_sz - dbg_line_sz)
+               dbg_rp = 0;
+
+       dsp_mem_disable(dbg_buf);
+}
+
+#ifdef OLD_BINARY_SUPPORT
+static void mbx1_dbg_old(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       char s[80], *s_end = &s[79], *p;
+       unsigned short *src;
+       volatile unsigned short *buf;
+       int cnt;
+       int i;
+
+       if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
+           (tid != OMAP_DSP_TID_ANON)) {
+               printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
+               return;
+       }
+       if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
+               printk(KERN_ERR "mbx: DBG - IPBUF sync failed!\n");
+               return;
+       }
+       buf = ipbuf_sys_da->d;
+       cnt = buf[0];
+       src = MKVIRT(buf[1], buf[2]);
+       if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
+               return;
+
+       if (dsp_mem_enable(src) < 0)
+               return;
+
+       p = s;
+       for (i = 0; i < cnt; i++) {
+               unsigned short tmp;
+               /*
+                * Be carefull that ipbuf should not be read with
+                * 1-byte access since it might be placed in DARAM/SARAM
+                * and it can cause unexpected byteswap.
+                * For example,
+                *   *(p++) = *(src++) & 0xff;
+                * causes 1-byte access!
+                */
+               tmp = *src++;
+               *(p++) = tmp & 0xff;
+               if (*(p-1) == '\n') {
+                       *p = '\0';
+                       printk(KERN_INFO "%s", s);
+                       p = s;
+                       continue;
+               }
+               if (p == s_end) {
+                       *p = '\0';
+                       printk(KERN_INFO "%s\n", s);
+                       p = s;
+                       continue;
+               }
+       }
+       if (p > s) {
+               *p = '\0';
+               printk(KERN_INFO "%s\n", s);
+       }
+
+       release_ipbuf_pvt(ipbuf_sys_da);
+       dsp_mem_disable(src);
+}
+#endif /* OLD_BINARY_SUPPORT */
+
+/*
+ * sysfs files
+ */
+static ssize_t devname_show(struct device *d, struct device_attribute *attr,
+                           char *buf)
+{
+       struct taskdev *dev = to_taskdev(d);
+       return sprintf(buf, "%s\n", dev->name);
+}
+
+static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
+                            char *buf)
+{
+       struct taskdev *dev = to_taskdev(d);
+       return sprintf(buf, "%s\n", devstate_name(dev->state));
+}
+
+static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
+                             char *buf)
+{
+       struct taskdev *dev;
+       struct proc_list *pl;
+       int len = 0;
+
+       dev = to_taskdev(d);
+       spin_lock(&dev->state_lock);
+       list_for_each_entry(pl, &dev->proc_list, list_head) {
+               len += sprintf(buf + len, "%d\n", pl->tsk->pid);
+       }
+       spin_unlock(&dev->state_lock);
+
+       return len;
+}
+
+static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
+                            char *buf)
+{
+       struct taskdev *dev = to_taskdev(d);
+       int len;
+
+       len = sprintf(buf, "%s\n", dev->task->name);
+
+       return len;
+}
+
+static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
+                        char *buf)
+{
+       unsigned short ttyp = to_taskdev(d)->task->ttyp;
+       int len = 0;
+
+       len += sprintf(buf + len, "0x%04x\n", ttyp);
+       len += sprintf(buf + len, "%s %s send\n",
+                       (sndtyp_acv(ttyp)) ? "active" :
+                                            "passive",
+                       (sndtyp_wd(ttyp))  ? "word" :
+                       (sndtyp_pvt(ttyp)) ? "private block" :
+                                            "global block");
+       len += sprintf(buf + len, "%s %s receive\n",
+                       (rcvtyp_acv(ttyp)) ? "active" :
+                                            "passive",
+                       (rcvtyp_wd(ttyp))  ? "word" :
+                       (rcvtyp_pvt(ttyp)) ? "private block" :
+                                            "global block");
+
+       return len;
+}
+
+static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
+                          char *buf)
+{
+       struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
+       return sprintf(buf, "%d\n", fifo->sz);
+}
+
+static int fifosz_store(struct device *d, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct dsptask *task = to_taskdev(d)->task;
+       unsigned long fifosz;
+       int ret;
+
+       fifosz = simple_strtol(buf, NULL, 10);
+       ret = dsp_task_set_fifosz(task, fifosz);
+
+       return (ret < 0) ? ret : strlen(buf);
+}
+
+static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
+                           char *buf)
+{
+       struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
+       return sprintf(buf, "%d\n", fifo->cnt);
+}
+
+static __inline__ char *bid_name(unsigned short bid)
+{
+       static char s[6];
+
+       switch (bid) {
+       case OMAP_DSP_BID_NULL:
+               return "NULL";
+       case OMAP_DSP_BID_PVT:
+               return "PRIVATE";
+       default:
+               sprintf(s, "%d", bid);
+               return s;
+       }
+}
+
+static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
+                           char *buf)
+{
+       struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->task->rcvdt.bk;
+       int len;
+
+       spin_lock(&rcvdt->link.lock);
+       len = sprintf(buf, "top  %s\ntail %s\n",
+                     bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail));
+       spin_unlock(&rcvdt->link.lock);
+
+       return len;
+}
+
+static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
+                       char *buf)
+{
+       return sprintf(buf, "%d\n", to_taskdev(d)->task->wsz);
+}
+
+static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
+                        char *buf)
+{
+       struct dsptask *task = to_taskdev(d)->task;
+       return sprintf(buf, "0x%p 0x%x\n", task->map_base, task->map_length);
+}
+
+/*
+ * called from ipbuf_read_proc()
+ */
+int ipbuf_is_held(unsigned char tid, unsigned short bid)
+{
+       struct dsptask *task = dsptask[tid];
+       unsigned short b;
+       int ret = 0;
+
+       if (task == NULL)
+               return 0;
+
+       spin_lock(&task->rcvdt.bk.link.lock);
+       ipblink_for_each(b, &task->rcvdt.bk.link, ipbuf) {
+               if (b == bid) { /* found */
+                       ret = 1;
+                       break;
+               }
+       }
+       spin_unlock(&task->rcvdt.bk.link.lock);
+
+       return ret;
+}
+
+int __init dsp_taskmod_init(void)
+{
+       int retval;
+
+       memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
+       memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
+
+       retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask",
+                                &dsp_task_fops);
+       if (retval < 0) {
+               printk(KERN_ERR
+                      "omapdsp: failed to register task device: %d\n", retval);
+               return retval;
+       }
+
+       bus_register(&dsptask_bus);
+       retval = driver_register(&dsptask_driver);
+       if (retval) {
+               printk(KERN_ERR
+                      "omapdsp: failed to register DSP task driver: %d\n",
+                      retval);
+               bus_unregister(&dsptask_bus);
+               unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
+               return -EINVAL;
+       }
+       dsp_task_class = class_create(THIS_MODULE, "dsptask");
+
+       return 0;
+}
+
+void dsp_taskmod_exit(void)
+{
+       class_destroy(dsp_task_class);
+       driver_unregister(&dsptask_driver);
+       bus_unregister(&dsptask_bus);
+       unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
+}
diff --git a/arch/arm/plat-omap/dsp/taskwatch.c b/arch/arm/plat-omap/dsp/taskwatch.c
new file mode 100644 (file)
index 0000000..b09c59d
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/taskwatch.c
+ *
+ * OMAP DSP task watch device driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 200%/05/16:  DSP Gateway version 3.3
+ */
+
+#include <linux/module.h>
+#include <linux/major.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/arch/dsp.h>
+#include "dsp.h"
+
+static DECLARE_WAIT_QUEUE_HEAD(read_wait_q);
+static unsigned int change_cnt;
+
+void dsp_twch_touch(void)
+{
+       change_cnt++;
+       wake_up_interruptible(&read_wait_q);
+}
+
+/*
+ * @count: represents the device counts of the user's interst
+ */
+static ssize_t dsp_twch_read(struct file *file, char *buf, size_t count,
+                            loff_t *ppos)
+{
+       long taskstat[TASKDEV_MAX];
+       int devcount = count / sizeof(long);
+       int i;
+
+       if (!dsp_is_ready()) {
+               printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
+               return -EINVAL;
+       }
+
+       if (change_cnt == 0) {
+               long current_state;
+               DECLARE_WAITQUEUE(wait, current);
+
+               add_wait_queue(&read_wait_q, &wait);
+               current_state = current->state;
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (change_cnt == 0)    /* last check */
+                       schedule();
+               set_current_state(current_state);
+               remove_wait_queue(&read_wait_q, &wait);
+
+               /* unconfigured while waiting ;-( */
+               if (dsp_is_ready())
+                       return -EINVAL;
+       }
+
+       if (devcount > TASKDEV_MAX)
+               devcount = TASKDEV_MAX;
+
+       count = devcount * sizeof(long);
+       change_cnt = 0;
+       for (i = 0; i < devcount; i++) {
+               /*
+                * once the device state is read, the 'STALE' bit will be set
+                * so that the Dynamic Loader can distinguish the new request
+                * from the old one.
+                */
+               taskstat[i] = taskdev_state_stale(i);
+       }
+
+       if (copy_to_user(buf, taskstat, count))
+               return -EFAULT;
+
+       return count;
+}
+
+static unsigned int dsp_twch_poll(struct file *file, poll_table *wait)
+{
+       unsigned int mask = 0;
+
+       poll_wait(file, &read_wait_q, wait);
+       if (change_cnt)
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+
+static int dsp_twch_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       static DECLARE_MUTEX(ioctl_sem);
+       int ret;
+
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       switch (cmd) {
+       case OMAP_DSP_TWCH_IOCTL_MKDEV:
+               {
+                       char name[OMAP_DSP_TNM_LEN];
+                       if (copy_from_user(name, (void *)arg, OMAP_DSP_TNM_LEN)) {
+                               ret = -EFAULT;
+                               goto up_out;
+                       }
+                       name[OMAP_DSP_TNM_LEN-1] = '\0';
+                       ret = dsp_mkdev(name);
+                       break;
+               }
+
+       case OMAP_DSP_TWCH_IOCTL_RMDEV:
+               {
+                       char name[OMAP_DSP_TNM_LEN];
+                       if (copy_from_user(name, (void *)arg, OMAP_DSP_TNM_LEN)) {
+                               ret = -EFAULT;
+                               goto up_out;
+                       }
+                       name[OMAP_DSP_TNM_LEN-1] = '\0';
+                       ret = dsp_rmdev(name);
+                       break;
+               }
+
+       case OMAP_DSP_TWCH_IOCTL_TADD:
+               {
+                       struct omap_dsp_taddinfo ti;
+                       if (copy_from_user(&ti, (void *)arg, sizeof(ti))) {
+                               ret = -EFAULT;
+                               goto up_out;
+                       }
+                       ret = dsp_tadd(ti.minor, ti.taskadr);
+                       break;
+               }
+
+       case OMAP_DSP_TWCH_IOCTL_TDEL:
+               ret = dsp_tdel(arg);
+               break;
+
+       case OMAP_DSP_TWCH_IOCTL_TKILL:
+               ret = dsp_tkill(arg);
+               break;
+
+       default:
+               ret = -ENOIOCTLCMD;
+       }
+
+up_out:
+       up(&ioctl_sem);
+       return ret;
+}
+
+struct file_operations dsp_twch_fops = {
+       .owner = THIS_MODULE,
+       .read  = dsp_twch_read,
+       .poll  = dsp_twch_poll,
+       .ioctl = dsp_twch_ioctl,
+};
+
+void dsp_twch_start(void)
+{
+       change_cnt = 1;         /* first read will not wait */
+}
+
+void dsp_twch_stop(void)
+{
+       wake_up_interruptible(&read_wait_q);
+}
diff --git a/arch/arm/plat-omap/dsp/uaccess_dsp.S b/arch/arm/plat-omap/dsp/uaccess_dsp.S
new file mode 100644 (file)
index 0000000..3257b70
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/uaccess_dsp.S
+ *
+ * user memory access functions for DSP driver
+ *
+ * Copyright (C) 2004,2005 Nokia Corporation
+ *
+ * Written by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2004/06/29:  DSP Gateway version 3.3
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+               .text
+
+/* Prototype: int __arch_copy_to_user_dsp_2b(void *to, const char *from)
+ * Purpose  : copy 2 bytes to user memory from kernel(DSP) memory
+ *            escaping from unexpected byte swap using __arch_copy_to_user()
+ *            in OMAP architecture.
+ * Params   : to   - user memory
+ *          : from - kernel(DSP) memory
+ * Returns  : success = 0, failure = 2
+ */
+
+ENTRY(__arch_copy_to_user_dsp_2b)
+               stmfd   sp!, {r4, lr}
+               ldrb    r3, [r1], #1
+               ldrb    r4, [r1], #1
+USER(          strbt   r4, [r0], #1)                   @ May fault
+USER(          strbt   r3, [r0], #1)                   @ May fault
+               mov     r0, #0
+               LOADREGS(fd,sp!,{r4, pc})
+
+               .section .fixup,"ax"
+               .align  0
+9001:          mov     r0, #2
+               LOADREGS(fd,sp!, {r4, pc})
+               .previous
+
+/* Prototype: unsigned long __arch_copy_from_user_dsp_2b(void *to, const void *from);
+ * Purpose  : copy 2 bytes from user memory to kernel(DSP) memory
+ *            escaping from unexpected byte swap using __arch_copy_to_user()
+ *            in OMAP architecture.
+ * Params   : to   - kernel (DSP) memory
+ *          : from - user memory
+ * Returns  : success = 0, failure = 2
+ */
+
+ENTRY(__arch_copy_from_user_dsp_2b)
+               stmfd   sp!, {r4, lr}
+USER(          ldrbt   r3, [r1], #1)                   @ May fault
+USER(          ldrbt   r4, [r1], #1)                   @ May fault
+               strb    r4, [r0], #1
+               strb    r3, [r0], #1
+               mov     r0, #0
+               LOADREGS(fd,sp!,{r4, pc})
+
+               .section .fixup,"ax"
+               .align  0
+9001:          mov     r3, #0
+               strh    r3, [r0], #2
+               mov     r0, #2
+               LOADREGS(fd,sp!, {r4, pc})
+               .previous
diff --git a/arch/arm/plat-omap/dsp/uaccess_dsp.h b/arch/arm/plat-omap/dsp/uaccess_dsp.h
new file mode 100644 (file)
index 0000000..2217a10
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * linux/arch/arm/mach-omap/dsp/uaccess_dsp.h
+ *
+ * Header for user access functions for DSP driver
+ *
+ * Copyright (C) 2002-2005 Nokia Corporation
+ *
+ * Modified from linux/include/asm-arm/uaccess.h
+ * by Toshihiro Kobayashi <toshihiro.kobayashi@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
+ *
+ * 2004/06/29:  DSP Gateway version 3.3
+ */
+
+#ifndef _OMAP_DSP_UACCESS_DSP_H
+#define _OMAP_DSP_UACCESS_DSP_H
+
+#include <asm/uaccess.h>
+
+#define HAVE_ASM_COPY_FROM_USER_DSP_2B
+
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+extern unsigned long __arch_copy_from_user_dsp_2b(void *to,
+                                                 const void __user *from);
+extern unsigned long __arch_copy_to_user_dsp_2b(void __user *to,
+                                               const void *from);
+#endif
+
+extern unsigned long dspmem_base, dspmem_size;
+#define is_dsp_internal_mem(va) \
+       (((unsigned long)(va) >= dspmem_base) &&  \
+        ((unsigned long)(va) < dspmem_base + dspmem_size))
+
+
+#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
+static __inline__ unsigned long copy_from_user_dsp_2b(void *to,
+                                                     const void *from)
+{
+       unsigned short tmp;
+
+       if (__arch_copy_from_user(&tmp, from, 2))
+               return 2;
+       /* expecting compiler to generate "strh" instruction */
+       *((unsigned short *)to) = tmp;
+       return 0;
+}
+#endif
+
+/*
+ * @n must be multiple of 2
+ */
+static __inline__ unsigned long copy_from_user_dsp(void *to, const void *from,
+                                                  unsigned long n)
+{
+       if (access_ok(VERIFY_READ, from, n)) {
+               if ((is_dsp_internal_mem(to)) &&
+                   (((unsigned long)to & 2) || (n & 2))) {
+                       /*
+                        * DARAM/SARAM with odd word alignment
+                        */
+                       unsigned long n4;
+                       unsigned long last_n;
+
+                       /* dest not aligned -- copy 2 bytes */
+                       if (((unsigned long)to & 2) && (n >= 2)) {
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+                               if (__arch_copy_from_user_dsp_2b(to, from))
+#else
+                               if (copy_from_user_dsp_2b(to, from))
+#endif
+                                       return n;
+                               to += 2;
+                               from += 2;
+                               n -= 2;
+                       }
+                       /* middle 4*n bytes */
+                       last_n = n & 2;
+                       n4 = n - last_n;
+                       if ((n = __arch_copy_from_user(to, from, n4)) != 0)
+                               return n + last_n;
+                       /* last 2 bytes */
+                       if (last_n) {
+                               to += n4;
+                               from += n4;
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+                               if (__arch_copy_from_user_dsp_2b(to, from))
+#else
+                               if (copy_from_user_dsp_2b(to, from))
+#endif
+                                       return 2;
+                               n = 0;
+                       }
+               } else {
+                       /*
+                        * DARAM/SARAM with 4-byte alignment or
+                        * external memory
+                        */
+                       n = __arch_copy_from_user(to, from, n);
+               }
+       }
+       else    /* security hole - plug it */
+               memzero(to, n);
+       return n;
+}
+
+#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
+static __inline__ unsigned long copy_to_user_dsp_2b(void *to, const void *from)
+{
+       /* expecting compiler to generate "strh" instruction */
+       unsigned short tmp = *(unsigned short *)from;
+
+       return __arch_copy_to_user(to, &tmp, 2);
+}
+#endif
+
+/*
+ * @n must be multiple of 2
+ */
+static __inline__ unsigned long copy_to_user_dsp(void *to, const void *from,
+                                                unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n)) {
+               if ((is_dsp_internal_mem(from)) &&
+                   (((unsigned long)to & 2) || (n & 2))) {
+                       /*
+                        * DARAM/SARAM with odd word alignment
+                        */
+                       unsigned long n4;
+                       unsigned long last_n;
+
+                       /* dest not aligned -- copy 2 bytes */
+                       if (((unsigned long)to & 2) && (n >= 2)) {
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+                               if (__arch_copy_to_user_dsp_2b(to, from))
+#else
+                               if (copy_to_user_dsp_2b(to, from))
+#endif
+                                       return n;
+                               to += 2;
+                               from += 2;
+                               n -= 2;
+                       }
+                       /* middle 4*n bytes */
+                       last_n = n & 2;
+                       n4 = n - last_n;
+                       if ((n = __arch_copy_to_user(to, from, n4)) != 0)
+                               return n + last_n;
+                       /* last 2 bytes */
+                       if (last_n) {
+                               to += n4;
+                               from += n4;
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+                               if (__arch_copy_to_user_dsp_2b(to, from))
+#else
+                               if (copy_to_user_dsp_2b(to, from))
+#endif
+                                       return 2;
+                               n = 0;
+                       }
+               } else {
+                       /*
+                        * DARAM/SARAM with 4-byte alignment or
+                        * external memory
+                        */
+                       n = __arch_copy_to_user(to, from, n);
+               }
+       }
+       return n;
+}
+
+#undef is_dsp_internal_mem
+
+#endif /* _OMAP_DSP_UACCESS_DSP_H */
diff --git a/arch/arm/plat-omap/gpio-switch.c b/arch/arm/plat-omap/gpio-switch.c
new file mode 100644 (file)
index 0000000..787e88d
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ *  linux/arch/arm/plat-omap/gpio-switch.c
+ *
+ *  Copyright (C) 2004, 2005 Nokia Corporation
+ *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
+ *         and 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/timer.h>
+#include <linux/err.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/board.h>
+
+struct gpio_switch {
+       char            name[14];
+       u16             gpio;
+       int             flags;
+       int             type;
+       int             key_code;
+       int             state;
+
+       struct work_struct      work;
+       struct timer_list       timer;
+       struct platform_device  pdev;
+
+       struct list_head        node;
+};
+
+static LIST_HEAD(gpio_switches);
+static struct platform_device *gpio_sw_platform_dev;
+static struct device_driver gpio_sw_driver;
+
+static const char *cover_str[2] = { "open", "closed" };
+static const char *connection_str[2] = { "disconnected", "connected" };
+
+/*
+ * GPIO switch state poll delay in ms
+ */
+#define OMAP_GPIO_SW_POLL_DELAY        10
+
+static void print_sw_state(struct gpio_switch *sw, int state)
+{
+       const char **str;
+
+       switch (sw->type) {
+       case OMAP_GPIO_SWITCH_TYPE_COVER:
+               str = cover_str;
+               break;
+       case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
+               str = connection_str;
+               break;
+       default:
+               str = NULL;
+       }
+       if (str != NULL)
+               printk(KERN_INFO "%s (GPIO %d) is now %s\n", sw->name, sw->gpio, str[state]);
+}
+
+static int gpio_sw_get_state(struct gpio_switch *sw)
+{
+       int state;
+
+       state = omap_get_gpio_datain(sw->gpio);
+       if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
+               state = !state;
+
+       return state;
+}
+
+static ssize_t gpio_sw_store(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf,
+                            size_t count)
+{
+       struct gpio_switch *sw = dev_get_drvdata(dev);
+       int enable = (int)simple_strtoul(buf, NULL, 10);
+       omap_set_gpio_dataout(sw->gpio, enable);
+       return count;
+}
+
+#define gpio_sw_switch_attr(name)                                      \
+static ssize_t gpio_sw_show_##name(struct device *dev,                 \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct gpio_switch *sw = dev_get_drvdata(dev);                  \
+       return sprintf(buf, "%s\n", name##_str[gpio_sw_get_state(sw)]); \
+}                                                                      \
+static DEVICE_ATTR(name##_switch, S_IRUGO | S_IWUSR,                   \
+                  gpio_sw_show_##name, gpio_sw_store)
+
+gpio_sw_switch_attr(cover);
+gpio_sw_switch_attr(connection);
+
+static irqreturn_t gpio_sw_irq_handler(int irq, void *arg, struct pt_regs *regs)
+{
+       struct gpio_switch *sw = arg;
+
+       mod_timer(&sw->timer, jiffies + OMAP_GPIO_SW_POLL_DELAY / (1000 / HZ));
+
+       return IRQ_HANDLED;
+}
+
+static void gpio_sw_timer(unsigned long arg)
+{
+       struct gpio_switch *sw = (struct gpio_switch *)arg;
+
+       schedule_work(&sw->work);
+}
+
+static void gpio_sw_handler(void *data)
+{
+       struct gpio_switch *sw = data;
+       int state = gpio_sw_get_state(sw);
+
+       if (sw->state == state)
+               return;
+
+       if (sw->type == OMAP_GPIO_SWITCH_TYPE_CONNECTION)
+               kobject_uevent(&sw->pdev.dev.kobj, KOBJ_CHANGE,
+                              &dev_attr_connection_switch.attr);
+       else
+               kobject_uevent(&sw->pdev.dev.kobj, KOBJ_CHANGE,
+                              &dev_attr_cover_switch.attr);
+       sw->state = state;
+       if (omap_get_gpio_datain(sw->gpio))
+               set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQT_FALLING);
+       else
+               set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQT_RISING);
+       print_sw_state(sw, state);
+}
+
+static int __init new_switch(struct gpio_switch *sw)
+{
+       int r, direction;
+
+       sw->pdev.name   = sw->name;
+       sw->pdev.id     = -1;
+
+       sw->pdev.dev.parent = &gpio_sw_platform_dev->dev;
+       sw->pdev.dev.driver = &gpio_sw_driver;
+
+       r = platform_device_register(&sw->pdev);
+       if (r)
+               return r;
+
+       dev_set_drvdata(&sw->pdev.dev, sw);
+
+       r = omap_request_gpio(sw->gpio);
+       if (r < 0) {
+               platform_device_unregister(&sw->pdev);
+               return r;
+       }
+
+       /* input: 1, output: 0 */
+       direction = !(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT);
+       omap_set_gpio_direction(sw->gpio, direction);
+
+       if (omap_get_gpio_datain(sw->gpio))
+               set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQT_FALLING);
+       else
+               set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQT_RISING);
+
+       switch (sw->type) {
+       case OMAP_GPIO_SWITCH_TYPE_COVER:
+               device_create_file(&sw->pdev.dev, &dev_attr_cover_switch);
+               break;
+       case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
+               device_create_file(&sw->pdev.dev, &dev_attr_connection_switch);
+               break;
+       }
+
+       list_add(&sw->node, &gpio_switches);
+
+       if (!direction)
+               return 0;
+
+       r = request_irq(OMAP_GPIO_IRQ(sw->gpio), gpio_sw_irq_handler, SA_SHIRQ,
+                       sw->name, sw);
+       if (r < 0) {
+               printk(KERN_ERR "gpio-switch: request_irq() failed "
+                               "for GPIO %d\n", sw->gpio);
+               platform_device_unregister(&sw->pdev);
+               omap_free_gpio(sw->gpio);
+               return r;
+       }
+
+       INIT_WORK(&sw->work, gpio_sw_handler, sw);
+       init_timer(&sw->timer);
+
+       sw->timer.function = gpio_sw_timer;
+       sw->timer.data = (unsigned long)sw;
+
+       return 0;
+}
+
+static int __init add_atag_switches(void)
+{
+       const struct omap_gpio_switch_config *cfg;
+       struct gpio_switch *sw;
+       int i, r;
+
+       for (i = 0; ; i++) {
+               cfg = omap_get_nr_config(OMAP_TAG_GPIO_SWITCH,
+                                        struct omap_gpio_switch_config, i);
+               if (cfg == NULL)
+                       break;
+               sw = kmalloc(sizeof(*sw), GFP_KERNEL);
+               if (sw == NULL) {
+                       printk(KERN_ERR "gpio-switch: kmalloc failed\n");
+                       return -ENOMEM;
+               }
+               memset(sw, 0, sizeof(*sw));
+               strncpy(sw->name, cfg->name, sizeof(cfg->name));
+               sw->gpio = cfg->gpio;
+               sw->flags = cfg->flags;
+               sw->type = cfg->type;
+               sw->key_code = cfg->key_code;
+               sw->state = gpio_sw_get_state(sw);
+               if ((r = new_switch(sw)) < 0) {
+                       kfree(sw);
+                       return r;
+               }
+       }
+       return 0;
+}
+
+static void gpio_sw_cleanup(void)
+{
+       struct gpio_switch *sw = NULL, *old = NULL;
+
+       list_for_each_entry(sw, &gpio_switches, node) {
+               kfree(old);
+
+               flush_scheduled_work();
+               del_timer_sync(&sw->timer);
+
+               free_irq(OMAP_GPIO_IRQ(sw->gpio), sw);
+
+               if (sw->type == OMAP_GPIO_SWITCH_TYPE_CONNECTION)
+                       device_remove_file(&sw->pdev.dev,
+                                          &dev_attr_connection_switch);
+               else
+                       device_remove_file(&sw->pdev.dev,
+                                          &dev_attr_cover_switch);
+
+               platform_device_unregister(&sw->pdev);
+               omap_free_gpio(sw->gpio);
+               old = sw;
+       }
+
+       kfree(sw);
+}
+
+static void __init report_initial_state(void)
+{
+       struct gpio_switch *sw;
+
+       list_for_each_entry(sw, &gpio_switches, node) {
+               int state;
+
+               state = omap_get_gpio_datain(sw->gpio);
+               if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
+                       state = !state;
+               print_sw_state(sw, state);
+       }
+}
+
+static void gpio_sw_shutdown(struct device *dev)
+{
+}
+
+static struct device_driver gpio_sw_driver = {
+       .name           = "gpio-switch",
+       .bus            = &platform_bus_type,
+       .shutdown       = gpio_sw_shutdown,
+};
+
+static int __init gpio_sw_init(void)
+{
+       int r;
+
+       printk(KERN_INFO "OMAP GPIO switch handler initializing\n");
+
+       r = driver_register(&gpio_sw_driver);
+       if (r)
+               return r;
+
+       gpio_sw_platform_dev = platform_device_register_simple("gpio-switch",
+                                                              -1, NULL, 0);
+       if (IS_ERR(gpio_sw_platform_dev)) {
+               driver_unregister(&gpio_sw_driver);
+               return PTR_ERR(gpio_sw_platform_dev);
+       }
+
+       r = add_atag_switches();
+       if (r < 0) {
+               platform_device_unregister(gpio_sw_platform_dev);
+               driver_unregister(&gpio_sw_driver);
+               gpio_sw_cleanup();
+               return r;
+       }
+
+       report_initial_state();
+
+       return 0;
+}
+
+static void __exit gpio_sw_exit(void)
+{
+       gpio_sw_cleanup();
+       platform_device_unregister(gpio_sw_platform_dev);
+       driver_unregister(&gpio_sw_driver);
+}
+
+#ifndef MODULE
+late_initcall(gpio_sw_init);
+#else
+module_init(gpio_sw_init);
+#endif
+module_exit(gpio_sw_exit);
+
+MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>, Paul Mundt <paul.mundt@nokia.com");
+MODULE_DESCRIPTION("GPIO switch driver");
+MODULE_LICENSE("GPL");
index 55059a24ad419da31fbc026f5345a9db386ee9fc..76f721d8513745280cfb7822331dea015cf2f327 100644 (file)
@@ -140,7 +140,7 @@ static struct gpio_bank gpio_bank_1610[5] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 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 }
@@ -173,7 +173,7 @@ static int gpio_bank_count;
 
 static inline struct gpio_bank *get_gpio_bank(int gpio)
 {
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                if (OMAP_GPIO_IS_MPUIO(gpio))
                        return &gpio_bank[0];
@@ -222,7 +222,7 @@ static inline int gpio_valid(int gpio)
                        return -1;
                return 0;
        }
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510() && gpio < 16)
                return 0;
 #endif
@@ -654,7 +654,7 @@ int omap_request_gpio(int gpio)
        /* Set trigger to none. You need to enable the trigger after request_irq */
        _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE);
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (bank->method == METHOD_GPIO_1510) {
                void __iomem *reg;
 
@@ -739,7 +739,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
        bank = (struct gpio_bank *) desc->data;
        if (bank->method == METHOD_MPUIO)
                isr_reg = bank->base + OMAP_MPUIO_GPIO_INT;
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (bank->method == METHOD_GPIO_1510)
                isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
 #endif
@@ -774,7 +774,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
                        d = irq_desc + gpio_irq;
                        desc_handle_irq(gpio_irq, d, regs);
                }
-        }
+       }
 }
 
 static void gpio_ack_irq(unsigned int irq)
@@ -837,8 +837,9 @@ static struct irqchip mpuio_irq_chip = {
        .unmask = mpuio_unmask_irq
 };
 
-static int initialized = 0;
-static struct clk * gpio_ck = NULL;
+static int initialized;
+static struct clk * gpio_ick;
+static struct clk * gpio_fck;
 
 static int __init _omap_gpio_init(void)
 {
@@ -848,14 +849,26 @@ static int __init _omap_gpio_init(void)
        initialized = 1;
 
        if (cpu_is_omap1510()) {
-               gpio_ck = clk_get(NULL, "arm_gpio_ck");
-               if (IS_ERR(gpio_ck))
+               gpio_ick = clk_get(NULL, "arm_gpio_ck");
+               if (IS_ERR(gpio_ick))
                        printk("Could not get arm_gpio_ck\n");
                else
-                       clk_use(gpio_ck);
+                       clk_use(gpio_ick);
+       }
+       if (cpu_is_omap24xx()) {
+               gpio_ick = clk_get(NULL, "gpios_ick");
+               if (IS_ERR(gpio_ick))
+                       printk("Could not get gpios_ick\n");
+               else
+                       clk_use(gpio_ick);
+               gpio_fck = clk_get(NULL, "gpios_fck");
+               if (IS_ERR(gpio_ick))
+                       printk("Could not get gpios_fck\n");
+               else
+                       clk_use(gpio_fck);
        }
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                printk(KERN_INFO "OMAP1510 GPIO hardware\n");
                gpio_bank_count = 2;
@@ -901,7 +914,7 @@ static int __init _omap_gpio_init(void)
                if (bank->method == METHOD_MPUIO) {
                        omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT);
                }
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
                if (bank->method == METHOD_GPIO_1510) {
                        __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK);
                        __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
@@ -1038,6 +1051,7 @@ static struct sys_device omap_gpio_device = {
 
 /*
  * This may get called early from board specific init
+ * for boards that have interrupts routed via FPGA.
  */
 int omap_gpio_init(void)
 {
index 9c9b7df3faf6d2fe15315899cda29e8d43a8466e..b0a393da5fc54171d94f69c3cd23affc3bb2beb6 100644 (file)
@@ -191,6 +191,7 @@ static int omap_mcbsp_check(unsigned int id)
 static void omap_mcbsp_dsp_request(void)
 {
        if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+               omap_dsp_request_mem();
                clk_use(mcbsp_dsp_ck);
                clk_use(mcbsp_api_ck);
 
@@ -209,6 +210,7 @@ static void omap_mcbsp_dsp_request(void)
 static void omap_mcbsp_dsp_free(void)
 {
        if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+               omap_dsp_release_mem();
                clk_unuse(mcbsp_dspxor_ck);
                clk_unuse(mcbsp_dsp_ck);
                clk_unuse(mcbsp_api_ck);
@@ -491,17 +493,20 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
        omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
                                     OMAP_DMA_DATA_TYPE_S16,
                                     length >> 1, 1,
-                                    OMAP_DMA_SYNC_ELEMENT);
+                                    OMAP_DMA_SYNC_ELEMENT,
+                                    0, 0);
 
        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);
+                                mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
+                                0, 0);
 
        omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
                                OMAP_DMA_PORT_EMIFF,
                                OMAP_DMA_AMODE_POST_INC,
-                               buffer);
+                               buffer,
+                               0, 0);
 
        omap_start_dma(mcbsp[id].dma_tx_lch);
        wait_for_completion(&(mcbsp[id].tx_dma_completion));
@@ -531,17 +536,20 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
        omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
                                     OMAP_DMA_DATA_TYPE_S16,
                                     length >> 1, 1,
-                                    OMAP_DMA_SYNC_ELEMENT);
+                                    OMAP_DMA_SYNC_ELEMENT,
+                                    0, 0);
 
        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);
+                               mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
+                               0, 0);
 
        omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
                                 OMAP_DMA_PORT_EMIFF,
                                 OMAP_DMA_AMODE_POST_INC,
-                                buffer);
+                                buffer,
+                                0, 0);
 
        omap_start_dma(mcbsp[id].dma_rx_lch);
        wait_for_completion(&(mcbsp[id].rx_dma_completion));
@@ -643,7 +651,7 @@ static const struct omap_mcbsp_info mcbsp_730[] = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 static const struct omap_mcbsp_info mcbsp_1510[] = {
        [0] = { .virt_base = OMAP1510_MCBSP1_BASE,
                .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
@@ -712,7 +720,7 @@ static int __init omap_mcbsp_init(void)
                mcbsp_count = ARRAY_SIZE(mcbsp_730);
        }
 #endif
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
                mcbsp_info = mcbsp_1510;
                mcbsp_count = ARRAY_SIZE(mcbsp_1510);
index 64482040f89e9a7c0da908cd0bb8429b4ac5e274..8c1c016aa68980db04bdcb1704d9df58308cf63c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h
  *
- * Copyright (C) 2003 Nokia Corporation
+ * Copyright (C) 2003 - 2005 Nokia Corporation
  *
  * Written by Tony Lindgren <tony.lindgren@nokia.com>
  *
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kernel.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
 
+#define OMAP24XX_L4_BASE       0x48000000
+#define OMAP24XX_PULL_ENA      (1 << 3)
+#define OMAP24XX_PULL_UP       (1 << 4)
+
+static struct pin_config * pin_table;
+static unsigned long pin_table_sz;
+
+extern struct pin_config * omap730_pins;
+extern struct pin_config * omap1xxx_pins;
+extern struct pin_config * omap24xx_pins;
+
+int __init omap_mux_register(struct pin_config * pins, unsigned long size)
+{
+       pin_table = pins;
+       pin_table_sz = size;
+
+       return 0;
+}
+
 /*
  * 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)
+int __init_or_module omap_cfg_reg(const unsigned long index)
 {
        static DEFINE_SPINLOCK(mux_spin_lock);
 
        unsigned long flags;
-       reg_cfg_set *cfg;
+       struct pin_config *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 (cpu_is_omap7xx())
-               return 0;
+       if (!pin_table)
+               BUG();
 
-       if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
-               printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
-               return -EINVAL;
+       if (index >= pin_table_sz) {
+               printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
+                      index, pin_table_sz);
+               dump_stack();
+               return -ENODEV;
        }
 
-       cfg = (reg_cfg_set *)&reg_cfg_table[reg_cfg];
+       cfg = (struct pin_config *)&pin_table[index];
+       if (cpu_is_omap24xx()) {
+               u8 reg = 0;
+
+               reg |= cfg->mask & 0x7;
+               if (cfg->pull_val)
+                       reg |= OMAP24XX_PULL_ENA;
+               if(cfg->pu_pd_val)
+                       reg |= OMAP24XX_PULL_UP;
+#ifdef CONFIG_OMAP_MUX_DEBUG
+               printk("Muxing %s (0x%08x): 0x%02x -> 0x%02x\n",
+                      cfg->name, OMAP24XX_L4_BASE + cfg->mux_reg,
+                      omap_readb(OMAP24XX_L4_BASE + cfg->mux_reg), reg);
+#endif
+               omap_writeb(reg, OMAP24XX_L4_BASE + cfg->mux_reg);
+
+               return 0;
+       }
 
        /* Check the mux register in question */
        if (cfg->mux_reg) {
@@ -157,7 +193,8 @@ omap_cfg_reg(const reg_cfg_t reg_cfg)
        return 0;
 #endif
 }
-
 EXPORT_SYMBOL(omap_cfg_reg);
-
+#else
+#define omap_mux_init() do {} while(0)
+#define omap_cfg_reg(x)        do {} while(0)
 #endif /* CONFIG_OMAP_MUX */
index e15c6c1ddec954775b68ac623738885675da04d4..f646e99a8729eef32644917ef5046cc0e9917733 100644 (file)
 #include <asm/arch/tps65010.h>
 #include <asm/arch/dsp_common.h>
 
-#include "clock.h"
-#include "sram.h"
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
 
 static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
 static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
+static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
 static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
 static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
 
@@ -120,8 +121,8 @@ void omap_pm_idle(void)
  */
 static void omap_pm_wakeup_setup(void)
 {
-       u32 level1_wake = OMAP_IRQ_BIT(INT_IH2_IRQ);
-       u32 level2_wake = OMAP_IRQ_BIT(INT_UART2) | OMAP_IRQ_BIT(INT_KEYBOARD);
+       u32 level1_wake = 0;
+       u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
 
        /*
         * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
@@ -129,19 +130,29 @@ static void omap_pm_wakeup_setup(void)
         * drivers must still separately call omap_set_gpio_wakeup() to
         * wake up to a GPIO interrupt.
         */
-       if (cpu_is_omap1510() || cpu_is_omap16xx())
-               level1_wake |= OMAP_IRQ_BIT(INT_GPIO_BANK1);
-       else if (cpu_is_omap730())
-               level1_wake |= OMAP_IRQ_BIT(INT_730_GPIO_BANK1);
+       if (cpu_is_omap730())
+               level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
+                       OMAP_IRQ_BIT(INT_730_IH2_IRQ);
+       else if (cpu_is_omap1510())
+               level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | 
+                       OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
+       else if (cpu_is_omap16xx())
+               level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+                       OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
 
        omap_writel(~level1_wake, OMAP_IH1_MIR);
 
-       if (cpu_is_omap1510())
+       if (cpu_is_omap730()) {
+               omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+               omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) | OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)), OMAP_IH2_1_MIR);
+       } else if (cpu_is_omap1510()) {
+               level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
                omap_writel(~level2_wake,  OMAP_IH2_MIR);
-
-       /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
-       if (cpu_is_omap16xx()) {
+       } else if (cpu_is_omap16xx()) {
+               level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
                omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+
+               /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
                omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR);
                omap_writel(~0x0, OMAP_IH2_2_MIR);
                omap_writel(~0x0, OMAP_IH2_3_MIR);
@@ -185,7 +196,17 @@ void omap_pm_suspend(void)
         * Save interrupt, MPUI, ARM and UPLD control registers.
         */
 
-       if (cpu_is_omap1510()) {
+       if (cpu_is_omap730()) {
+               MPUI730_SAVE(OMAP_IH1_MIR);
+               MPUI730_SAVE(OMAP_IH2_0_MIR);
+               MPUI730_SAVE(OMAP_IH2_1_MIR);
+               MPUI730_SAVE(MPUI_CTRL);
+               MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+               MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+               MPUI730_SAVE(EMIFS_CONFIG);
+               MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+
+       } else if (cpu_is_omap1510()) {
                MPUI1510_SAVE(OMAP_IH1_MIR);
                MPUI1510_SAVE(OMAP_IH2_MIR);
                MPUI1510_SAVE(MPUI_CTRL);
@@ -224,6 +245,7 @@ void omap_pm_suspend(void)
         * Step 4: OMAP DSP Shutdown
         */
 
+       omap_dsp_pm_suspend();
 
        /*
         * Step 5: Wakeup Event Setup
@@ -266,6 +288,9 @@ void omap_pm_suspend(void)
         * If we are here, processor is woken up!
         */
 
+       /* Restore DSP clocks */
+       omap_dsp_pm_resume();
+
        /*
         * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
         */
@@ -280,7 +305,13 @@ void omap_pm_suspend(void)
        ULPD_RESTORE(ULPD_CLOCK_CTRL);
        ULPD_RESTORE(ULPD_STATUS_REQ);
 
-       if (cpu_is_omap1510()) {
+       if (cpu_is_omap730()) {
+               MPUI730_RESTORE(EMIFS_CONFIG);
+               MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
+               MPUI730_RESTORE(OMAP_IH1_MIR);
+               MPUI730_RESTORE(OMAP_IH2_0_MIR);
+               MPUI730_RESTORE(OMAP_IH2_1_MIR);
+       } else if (cpu_is_omap1510()) {
                MPUI1510_RESTORE(MPUI_CTRL);
                MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
                MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
@@ -355,7 +386,14 @@ static int omap_pm_read_proc(
        ULPD_SAVE(ULPD_DPLL_CTRL);
        ULPD_SAVE(ULPD_POWER_CTRL);
 
-       if (cpu_is_omap1510()) {
+       if (cpu_is_omap730()) {
+               MPUI730_SAVE(MPUI_CTRL);
+               MPUI730_SAVE(MPUI_DSP_STATUS);
+               MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+               MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+               MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+               MPUI730_SAVE(EMIFS_CONFIG);
+       } else if (cpu_is_omap1510()) {
                MPUI1510_SAVE(MPUI_CTRL);
                MPUI1510_SAVE(MPUI_DSP_STATUS);
                MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
@@ -404,7 +442,21 @@ static int omap_pm_read_proc(
                   ULPD_SHOW(ULPD_STATUS_REQ),
                   ULPD_SHOW(ULPD_POWER_CTRL));
 
-               if (cpu_is_omap1510()) {
+               if (cpu_is_omap730()) {
+                       my_buffer_offset += sprintf(my_base + my_buffer_offset,
+                          "MPUI730_CTRL_REG         0x%-8x \n"
+                          "MPUI730_DSP_STATUS_REG:      0x%-8x \n"
+                          "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+        "MPUI730_DSP_API_CONFIG_REG:  0x%-8x \n"
+        "MPUI730_SDRAM_CONFIG_REG:    0x%-8x \n"
+        "MPUI730_EMIFS_CONFIG_REG:    0x%-8x \n",
+        MPUI730_SHOW(MPUI_CTRL),
+        MPUI730_SHOW(MPUI_DSP_STATUS),
+        MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
+        MPUI730_SHOW(MPUI_DSP_API_CONFIG),
+        MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
+        MPUI730_SHOW(EMIFS_CONFIG));
+               } else 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"
@@ -553,7 +605,12 @@ static int __init omap_pm_init(void)
         * These routines need to be in SRAM as that's the only
         * memory the MPU can see when it wakes up.
         */
-       if (cpu_is_omap1510()) {
+       if (cpu_is_omap730()) {
+               omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
+                                               omap730_idle_loop_suspend_sz);
+               omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
+        omap730_cpu_suspend_sz);
+       } else if (cpu_is_omap1510()) {
                omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
                                                omap1510_idle_loop_suspend_sz);
                omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
@@ -572,7 +629,11 @@ static int __init omap_pm_init(void)
 
        pm_idle = omap_pm_idle;
 
-       setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+       if (cpu_is_omap730())
+               setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
+       else if (cpu_is_omap16xx())
+               setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+
 #if 0
        /* --- BEGIN BOARD-DEPENDENT CODE --- */
        /* Sleepx mask direction */
@@ -591,7 +652,9 @@ static int __init omap_pm_init(void)
        omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
 
        /* Configure IDLECT3 */
-       if (cpu_is_omap16xx())
+       if (cpu_is_omap730())
+               omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
+       else if (cpu_is_omap16xx())
                omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
 
        pm_set_ops(&omap_pm_ops);
@@ -600,8 +663,10 @@ static int __init omap_pm_init(void)
        omap_pm_init_proc();
 #endif
 
-       /* configure LOW_PWR pin */
-       omap_cfg_reg(T20_1610_LOW_PWR);
+       if (cpu_is_omap16xx()) {
+               /* configure LOW_PWR pin */
+               omap_cfg_reg(T20_1610_LOW_PWR);
+       }
 
        return 0;
 }
index 9f745836f6aac97e8b76e8e61c9b516d3d4bf388..4cd7d292f854be9c5b743829081ac0dcdbce2279 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/plat-omap/sleep.S
  *
- * Low-level OMAP1510/1610 sleep/wakeUp support
+ * Low-level OMAP730/1510/1610 sleep/wakeUp support
  *
  * Initial SA1110 code:
  * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
  *       processor specific functions here.
  */
 
-#ifdef CONFIG_ARCH_OMAP1510
+#if defined(CONFIG_ARCH_OMAP730)
+ENTRY(omap730_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, #OMAP730_IDLECT2_SLEEP_VAL & 0xff
+       orr     r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 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, #OMAP730_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_730: subs    r5, r5, #1
+       bne     l_730
+/*
+ * 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
+/*
+ * omap730_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(omap730_idle_loop_suspend_sz)
+       .word   . - omap730_idle_loop_suspend
+#endif /* CONFIG_ARCH_OMAP730 */
+
+#ifdef CONFIG_ARCH_OMAP15XX
 ENTRY(omap1510_idle_loop_suspend)
 
        stmfd   sp!, {r0 - r12, lr}             @ save registers on stack
@@ -100,7 +150,7 @@ l_1510:     subs    r5, r5, #1
 
 ENTRY(omap1510_idle_loop_suspend_sz)
        .word   . - omap1510_idle_loop_suspend
-#endif /* CONFIG_ARCH_OMAP1510 */
+#endif /* CONFIG_ARCH_OMAP15XX */
 
 #if defined(CONFIG_ARCH_OMAP16XX)
 ENTRY(omap1610_idle_loop_suspend)
@@ -169,7 +219,86 @@ ENTRY(omap1610_idle_loop_suspend_sz)
  *
  */
 
-#ifdef CONFIG_ARCH_OMAP1510
+#if defined(CONFIG_ARCH_OMAP730)
+ENTRY(omap730_cpu_suspend)
+
+       @ save registers on stack
+       stmfd   sp!, {r0 - r12, lr}
+
+       @ Drain write cache
+       mov     r4, #0
+       mcr     p15, 0, r0, c7, c10, 4
+       nop
+
+       @ load base address of Traffic Controller
+       mov     r6, #TCMIF_ASM_BASE & 0xff000000
+       orr     r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
+       orr     r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
+
+       @ prepare to put SDRAM into self-refresh manually
+       ldr     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+       orr     r9, r7, #SELF_REFRESH_MODE & 0xff000000
+       orr     r9, r9, #SELF_REFRESH_MODE & 0x000000ff
+       str     r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+
+       @ prepare to put EMIFS to Sleep
+       ldr     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+       orr     r9, r8, #IDLE_EMIFS_REQUEST & 0xff
+       str     r9, [r6, #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
+       @ do not disable PERCK (0x04)
+       mov     r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff
+       orr     r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00
+       strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+       @ request ARM idle
+       mov     r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff
+       orr     r3, r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff00
+       strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+       @ disable instruction cache
+       mrc     p15, 0, r9, c1, c0, 0
+       bic     r2, r9, #0x1000
+       mcr     p15, 0, r2, c1, c0, 0
+       nop
+
+/*
+ * 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
+/*
+ * omap730_cpu_suspend()'s resume point.
+ *
+ * It will just start executing here, so we'll restore stuff from the
+ * stack.
+ */
+       @ re-enable Icache
+       mcr     p15, 0, r9, c1, c0, 0
+
+       @ reset the ARM_IDLECT1 and ARM_IDLECT2.
+       strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+       strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+       @ Restore EMIFF controls
+       str     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+       str     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+       @ restore regs and return
+       ldmfd   sp!, {r0 - r12, pc}
+
+ENTRY(omap730_cpu_suspend_sz)
+       .word   . - omap730_cpu_suspend
+#endif /* CONFIG_ARCH_OMAP730 */
+
+#ifdef CONFIG_ARCH_OMAP15XX
 ENTRY(omap1510_cpu_suspend)
 
        @ save registers on stack
@@ -241,7 +370,7 @@ l_1510_2:
 
 ENTRY(omap1510_cpu_suspend_sz)
        .word   . - omap1510_cpu_suspend
-#endif /* CONFIG_ARCH_OMAP1510 */
+#endif /* CONFIG_ARCH_OMAP15XX */
 
 #if defined(CONFIG_ARCH_OMAP16XX)
 ENTRY(omap1610_cpu_suspend)
index 7ad69f14a3e7fa16f8e7a4e74134a0bfb4c59869..792f66375830d11b607fffe69daa6a8945414144 100644 (file)
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
-#include "sram.h"
+#include <asm/arch/sram.h>
+
+#define OMAP1_SRAM_PA          0x20000000
+#define OMAP1_SRAM_VA          0xd0000000
+#define OMAP2_SRAM_PA          0x40200000
+#define OMAP2_SRAM_VA          0xd0000000
 
-#define OMAP1_SRAM_BASE                0xd0000000
-#define OMAP1_SRAM_START       0x20000000
 #define SRAM_BOOTLOADER_SZ     0x80
 
 static unsigned long omap_sram_base;
@@ -31,37 +34,40 @@ static unsigned long omap_sram_size;
 static unsigned long omap_sram_ceil;
 
 /*
- * The amount of SRAM depends on the core type:
- * 730 = 200K, 1510 = 512K, 5912 = 256K, 1610 = 16K, 1710 = 16K
+ * The amount of SRAM depends on the core type.
  * Note that we cannot try to test for SRAM here because writes
  * to secure SRAM will hang the system. Also the SRAM is not
  * yet mapped at this point.
  */
 void __init omap_detect_sram(void)
 {
-       omap_sram_base = OMAP1_SRAM_BASE;
+       if (!cpu_is_omap24xx())
+               omap_sram_base = OMAP1_SRAM_VA;
+       else
+               omap_sram_base = OMAP2_SRAM_VA;
 
        if (cpu_is_omap730())
-               omap_sram_size = 0x32000;
-       else if (cpu_is_omap1510())
-               omap_sram_size = 0x80000;
+               omap_sram_size = 0x32000;       /* 200K */
+       else if (cpu_is_omap15xx())
+               omap_sram_size = 0x30000;       /* 192K */
        else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
-               omap_sram_size = 0x4000;
+               omap_sram_size = 0x4000;        /* 16K */
        else if (cpu_is_omap1611())
-               omap_sram_size = 0x3e800;
+               omap_sram_size = 0x3e800;       /* 250K */
+       else if (cpu_is_omap2420())
+               omap_sram_size = 0xa0014;       /* 640K */
        else {
                printk(KERN_ERR "Could not detect SRAM size\n");
                omap_sram_size = 0x4000;
        }
 
-       printk(KERN_INFO "SRAM size: 0x%lx\n", omap_sram_size);
        omap_sram_ceil = omap_sram_base + omap_sram_size;
 }
 
 static struct map_desc omap_sram_io_desc[] __initdata = {
        {       /* .length gets filled in at runtime */
-               .virtual        = OMAP1_SRAM_BASE,
-               .pfn            = __phys_to_pfn(OMAP1_SRAM_START),
+               .virtual        = OMAP1_SRAM_VA,
+               .pfn            = __phys_to_pfn(OMAP1_SRAM_PA),
                .type           = MT_DEVICE
        }
 };
@@ -76,10 +82,19 @@ void __init omap_map_sram(void)
        if (omap_sram_size == 0)
                return;
 
+       if (cpu_is_omap24xx()) {
+               omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
+               omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA);
+       }
+
        omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
        omap_sram_io_desc[0].length *= PAGE_SIZE;
        iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
 
+       printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
+              omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual,
+              omap_sram_io_desc[0].length);
+
        /*
         * Looks like we need to preserve some bootloader code at the
         * beginning of SRAM for jumping to flash for reboot to work...
@@ -88,16 +103,6 @@ void __init omap_map_sram(void)
               omap_sram_size - SRAM_BOOTLOADER_SZ);
 }
 
-static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl) = NULL;
-
-void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
-{
-       if (_omap_sram_reprogram_clock == NULL)
-               panic("Cannot use SRAM");
-
-       return _omap_sram_reprogram_clock(dpllctl, ckctl);
-}
-
 void * omap_sram_push(void * start, unsigned long size)
 {
        if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
@@ -111,10 +116,94 @@ void * omap_sram_push(void * start, unsigned long size)
        return (void *)omap_sram_ceil;
 }
 
-void __init omap_sram_init(void)
+static void omap_sram_error(void)
+{
+       panic("Uninitialized SRAM function\n");
+}
+
+#ifdef CONFIG_ARCH_OMAP1
+
+static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl);
+
+void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
+{
+       if (!_omap_sram_reprogram_clock)
+               omap_sram_error();
+
+       return _omap_sram_reprogram_clock(dpllctl, ckctl);
+}
+
+int __init omap1_sram_init(void)
 {
-       omap_detect_sram();
-       omap_map_sram();
        _omap_sram_reprogram_clock = omap_sram_push(sram_reprogram_clock,
                                                    sram_reprogram_clock_sz);
+
+       return 0;
+}
+
+#else
+#define omap1_sram_init()      do {} while (0)
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+
+static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+                             u32 base_cs, u32 force_unlock);
+
+void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+                  u32 base_cs, u32 force_unlock)
+{
+       if (!_omap2_sram_ddr_init)
+               omap_sram_error();
+
+       return _omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
+                                   base_cs, force_unlock);
+}
+
+static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val,
+                                         u32 mem_type);
+
+void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
+{
+       if (!_omap2_sram_reprogram_sdrc)
+               omap_sram_error();
+
+       return _omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
+}
+
+static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
+
+u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
+{
+       if (!_omap2_set_prcm)
+               omap_sram_error();
+
+       return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass);
+}
+
+int __init omap2_sram_init(void)
+{
+       _omap2_sram_ddr_init = omap_sram_push(sram_ddr_init, sram_ddr_init_sz);
+
+       _omap2_sram_reprogram_sdrc = omap_sram_push(sram_reprogram_sdrc,
+                                                   sram_reprogram_sdrc_sz);
+       _omap2_set_prcm = omap_sram_push(sram_set_prcm, sram_set_prcm_sz);
+
+       return 0;
+}
+#else
+#define omap2_sram_init()      do {} while (0)
+#endif
+
+int __init omap_sram_init(void)
+{
+       omap_detect_sram();
+       omap_map_sram();
+
+       if (!cpu_is_omap24xx())
+               omap1_sram_init();
+       else
+               omap2_sram_init();
+
+       return 0;
 }
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h
deleted file mode 100644 (file)
index 71984ef..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/sram.h
- *
- * Interface for functions that need to be run in internal SRAM
- *
- * 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.
- */
-
-#ifndef __ARCH_ARM_OMAP_SRAM_H
-#define __ARCH_ARM_OMAP_SRAM_H
-
-extern void * omap_sram_push(void * start, unsigned long size);
-extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
-
-/* Do not use these */
-extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
-extern unsigned long sram_reprogram_clock_sz;
-
-#endif
index 205e2d0b826d4f4ff53f24c73a71970b88be10a2..00afc7a8c2ab036634392214358073235a4f4548 100644 (file)
@@ -91,6 +91,8 @@ EXPORT_SYMBOL(otg_set_transceiver);
 
 /*-------------------------------------------------------------------------*/
 
+#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP15XX)
+
 static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
 {
        u32     syscon1 = 0;
@@ -271,6 +273,8 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
        return syscon1 << 24;
 }
 
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 #if    defined(CONFIG_USB_GADGET_OMAP) || \
@@ -494,7 +498,7 @@ static inline void omap_otg_init(struct omap_usb_config *config) {}
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 
 #define ULPD_DPLL_CTRL_REG     __REG16(ULPD_DPLL_CTRL)
 #define DPLL_IOB               (1 << 13)
@@ -507,7 +511,6 @@ static inline void omap_otg_init(struct omap_usb_config *config) {}
 
 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));
@@ -539,6 +542,8 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config)
 
 #ifdef CONFIG_USB_GADGET_OMAP
        if (config->register_dev) {
+               int status;
+
                udc_device.dev.platform_data = config;
                status = platform_device_register(&udc_device);
                if (status)
@@ -549,6 +554,8 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config)
 
 #if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        if (config->register_host) {
+               int status;
+
                ohci_device.dev.platform_data = config;
                status = platform_device_register(&ohci_device);
                if (status)
index 48f446d3c671ade5a5198384c729f83118a35033..f28c10aba8d109ba1cb8411617ad41fa5131040e 100644 (file)
@@ -66,4 +66,6 @@ source "drivers/infiniband/Kconfig"
 
 source "drivers/sn/Kconfig"
 
+source "drivers/ssi/Kconfig"
+
 endmenu
index fac1e1603097d46bcc66e076c083601cfa37c52f..9749f6d59ea69a32c45b4daf129f69a066c3ec9b 100644 (file)
@@ -29,7 +29,9 @@ obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 obj-$(CONFIG_SERIO)            += input/serio/
 obj-y                          += serial/
 obj-$(CONFIG_PARPORT)          += parport/
-obj-y                          += base/ block/ misc/ mfd/ net/ media/
+obj-y                          += base/ block/ misc/ mfd/ net/
+obj-$(CONFIG_I2C)              += i2c/
+obj-y                          += media/ ssi/
 obj-$(CONFIG_NUBUS)            += nubus/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_PPC_PMAC)         += macintosh/
@@ -53,7 +55,6 @@ obj-$(CONFIG_USB_GADGET)      += usb/gadget/
 obj-$(CONFIG_GAMEPORT)         += input/gameport/
 obj-$(CONFIG_INPUT)            += input/
 obj-$(CONFIG_I2O)              += message/
-obj-$(CONFIG_I2C)              += i2c/
 obj-$(CONFIG_W1)               += w1/
 obj-$(CONFIG_HWMON)            += hwmon/
 obj-$(CONFIG_PHONE)            += telephony/
index fdf4370db994ca6f17be96070a0b2153a087764a..da5a65c58d7e149eb644f85434d56c809b334060 100644 (file)
@@ -659,6 +659,16 @@ config HW_RANDOM
 
          If unsure, say N.
 
+config OMAP_RNG
+       tristate "OMAP Random Number Generator support"
+       depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on OMAP16xx and OMAP24xx multimedia
+         processors.
+
+         If unsure, say N.
+
 config NVRAM
        tristate "/dev/nvram support"
        depends on ATARI || X86 || ARM || GENERIC_NVRAM
@@ -761,6 +771,11 @@ config GEN_RTC_X
 config EFI_RTC
        bool "EFI Real Time Clock Services"
        depends on IA64
+config OMAP_RTC
+       bool "TI OMAP Real Time Clock"
+       depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730
+       help
+         Support for TI OMAP RTC
 
 config DS1302
        tristate "DS1302 RTC support"
index 4aeae687e88a20e8911781ad5747a6ebb69d1948..63b2ae2602fb67618bf3c9604b43dade11faaef0 100644 (file)
@@ -65,6 +65,7 @@ obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
 obj-$(CONFIG_DS1302) += ds1302.o
 obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
 obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
+obj-$(CONFIG_OMAP_RTC)+= omap-rtc.o
 ifeq ($(CONFIG_GENERIC_NVRAM),y)
   obj-$(CONFIG_NVRAM) += generic_nvram.o
 else
@@ -74,6 +75,7 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o
 obj-$(CONFIG_I8K) += i8k.o
 obj-$(CONFIG_DS1620) += ds1620.o
 obj-$(CONFIG_HW_RANDOM) += hw_random.o
+obj-$(CONFIG_OMAP_RNG) += omap-rng.o
 obj-$(CONFIG_FTAPE) += ftape/
 obj-$(CONFIG_COBALT_LCD) += lcd.o
 obj-$(CONFIG_PPDEV) += ppdev.o
diff --git a/drivers/char/omap-rng.c b/drivers/char/omap-rng.c
new file mode 100644 (file)
index 0000000..a40f999
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * drivers/char/omap-rng.c
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * OMAP16xx and OMAP24xx Random Number Generator driver
+ *
+ * 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/random.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+#if defined (CONFIG_ARCH_OMAP16XX)
+#define RNG_BASE               0xfffe5000
+#endif
+#if defined (CONFIG_ARCH_OMAP24XX)
+#define RNG_BASE               0x480A0000
+#endif
+
+#define RNG_OUT_REG            0x00            /* Output register */
+#define RNG_STAT_REG           0x04            /* Status register
+                                                       [0] = STAT_BUSY */
+#define RNG_ALARM_REG          0x24            /* Alarm register
+                                                       [7:0] = ALARM_COUNTER */
+#define RNG_CONFIG_REG         0x28            /* Configuration register
+                                                       [11:6] = RESET_COUNT
+                                                       [5:3]  = RING2_DELAY 
+                                                       [2:0]  = RING1_DELAY */
+#define RNG_REV_REG            0x3c            /* Revision register
+                                                       [7:0] = REV_NB */
+#define RNG_MASK_REG           0x40            /* Mask and reset register
+                                                       [2] = IT_EN
+                                                       [1] = SOFTRESET
+                                                       [0] = AUTOIDLE */
+#define RNG_SYSSTATUS          0x44            /* System status
+                                                       [0] = RESETDONE */
+
+#define ENTROPY_WORD_COUNT     128
+
+static u32 rng_base = io_p2v(RNG_BASE);
+
+static struct clk *rng_ick = NULL;
+
+static u32 rng_read_reg(int reg)
+{
+       return __raw_readl(rng_base + reg);
+}
+
+static void rng_write_reg(int reg, u32 val)
+{
+       __raw_writel(val, rng_base + reg);
+}
+
+static void rng_feed_entropy(int count)
+{
+       u32 l;
+
+       while (count--) {
+               while (rng_read_reg(RNG_STAT_REG));
+               l = rng_read_reg(RNG_OUT_REG);
+               add_input_randomness(0, 0, l);
+       }
+}
+
+static int __init rng_init(void)
+{
+       if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
+               return -ENODEV;
+
+       if (cpu_is_omap24xx()) {
+               rng_ick = clk_get(NULL, "rng_ick");
+               if (IS_ERR(rng_ick)) {
+                       printk(KERN_ERR "omap-rng.c: Could not get rng_ick\n");
+                       return PTR_ERR(rng_ick);
+               }
+               clk_use(rng_ick);
+       }
+
+       printk("OMAP Random Number Generator ver. %02x\n",
+       rng_read_reg(RNG_REV_REG));
+       rng_write_reg(RNG_MASK_REG, 0x00000001);
+       rng_feed_entropy(ENTROPY_WORD_COUNT);
+       rng_write_reg(RNG_MASK_REG, 0x00000000);
+       printk("%d words of entropy generated\n", ENTROPY_WORD_COUNT);
+
+       return 0;
+}
+late_initcall(rng_init);
diff --git a/drivers/char/omap-rtc.c b/drivers/char/omap-rtc.c
new file mode 100644 (file)
index 0000000..814b614
--- /dev/null
@@ -0,0 +1,768 @@
+/*
+ *     TI OMAP Real Time Clock interface for Linux     
+ *
+ *     Copyright (C) 2003 MontaVista Software, Inc.
+ *      Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com>
+ *
+ *     Initially based on linux-2.4.20/drivers/char/rtc.c
+ *     Copyright (C) 1996 Paul Gortmaker
+ *
+ *     This driver allows use of the real time clock (built into
+ *     nearly all computers) from user space. It exports the /dev/rtc
+ *     interface supporting various ioctl() and also the
+ *     /proc/driver/rtc pseudo-file for status information.
+ *
+ *     The ioctls can be used to set the interrupt behaviour from the
+ *     RTC via IRQs. Then the /dev/rtc interface can be used to make
+ *     use of RTC interrupts, be they time update or alarm based.
+ *
+ *     The /dev/rtc interface will block on reads until an interrupt
+ *     has been received. If a RTC interrupt has already happened,
+ *     it will output an unsigned long and then block. The output value
+ *     contains the interrupt status in the low byte and the number of
+ *     interrupts since the last read in the remaining high bytes. The 
+ *     /dev/rtc interface can also be used with the select(2) call.
+ *
+ *     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.
+ *
+ *     Based on other minimal char device drivers, like Alan's
+ *     watchdog, Ted's random, etc. etc.
+ *
+ * Change Log :
+ *      v1.0    <gdavis@mvista.com> Initial version based on rtc.c v1.10e
+ *              <ramakrishnan@india.ti.com> Added support for 2.6 kernel, 
+ *                  - changed the return value of the interrupt handler
+ */
+
+/*
+ *     Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
+ *     interrupts disabled.
+ *     REVISIT: Elaborate on OMAP1510 TRM 15uS BUSY access rule.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+#include <asm/mach/time.h>
+
+#include "omap-rtc.h"
+
+extern spinlock_t rtc_lock;
+
+
+/* OMAP RTC register access macros: */
+
+#define CMOS_READ(addr)                omap_readb(addr)
+#define CMOS_WRITE(val, addr)  omap_writeb(val, addr)
+
+static struct fasync_struct *rtc_async_queue;
+
+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
+
+static void get_rtc_time (struct rtc_time *rtc_tm);
+static void get_rtc_alm_time (struct rtc_time *alm_tm);
+
+static void set_rtc_irq_bit(unsigned char bit);
+static void mask_rtc_irq_bit(unsigned char bit);
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+                         int count, int *eof, void *data);
+
+/*
+ *     Bits in rtc_status. (7 bits of room for future expansion)
+ */
+
+#define RTC_IS_OPEN            0x01    /* means /dev/rtc is in use     */
+
+/*
+ * REVISIT: fix this comment:
+ * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is
+ * protected by the big kernel lock.
+ */
+static unsigned long rtc_status = 0;   /* bitmapped status byte.       */
+static unsigned long rtc_irq_data = 0; /* our output to the world      */
+
+/*
+ *     If this driver ever becomes modularised, it will be really nice
+ *     to make the epoch retain its value across module reload...
+ */
+
+static unsigned long epoch = 1900;     /* year corresponding to 0x00   */
+
+static const unsigned char days_in_mo[] = 
+{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ *     A very tiny interrupt handler. It runs with SA_INTERRUPT set.
+ */
+
+static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /*
+        *      Either an alarm interrupt or update complete interrupt.
+        *      We store the status in the low byte and the number of
+        *      interrupts received since the last read in the remainder
+        *      of rtc_irq_data.
+        */
+
+       spin_lock (&rtc_lock);
+
+       rtc_irq_data += 0x100;
+       rtc_irq_data &= ~0xff;
+       rtc_irq_data |= CMOS_READ(OMAP_RTC_STATUS_REG);
+
+       if (rtc_irq_data & OMAP_RTC_STATUS_ALARM)
+               CMOS_WRITE(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+
+       spin_unlock (&rtc_lock);
+
+       /* Now do the rest of the actions */
+       wake_up_interruptible(&rtc_wait);       
+
+       kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
+       return IRQ_HANDLED;
+}
+
+/*
+ *     Now all the various file operations that we export.
+ */
+
+static ssize_t rtc_read(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long data;
+       ssize_t retval;
+       
+       if (count < sizeof(unsigned long))
+               return -EINVAL;
+
+       add_wait_queue(&rtc_wait, &wait);
+       set_current_state(TASK_INTERRUPTIBLE);
+
+       for (;;) {
+               spin_lock_irq (&rtc_lock);
+               data = rtc_irq_data;
+               if (data != 0) {
+                       rtc_irq_data = 0;
+                       break;
+               }
+               spin_unlock_irq (&rtc_lock);
+
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EAGAIN;
+                       goto out;
+               }
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       goto out;
+               }
+               schedule();
+       }
+
+       spin_unlock_irq (&rtc_lock);
+       retval = put_user(data, (unsigned long __user *)buf);
+       if (!retval)
+               retval = sizeof(unsigned long); 
+ out:
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&rtc_wait, &wait);
+
+       return retval;
+}
+
+/* convert from userspace struct to hardware BCD-encoded version,
+ * or return error code
+ */
+static int utm2bcd(struct rtc_time __user *arg, struct rtc_time *tm)
+{
+       unsigned char leap_yr;
+
+       if (copy_from_user(tm, arg, sizeof(struct rtc_time)))
+               return -EFAULT;
+
+       tm->tm_year += 1900;
+       tm->tm_mon++;
+
+       if (tm->tm_year < 1970)
+               return -EINVAL;
+
+       leap_yr = (!(tm->tm_year % 4) && (tm->tm_year % 100))
+                       || !(tm->tm_year % 400);
+
+       if ((tm->tm_mon > 12) || (tm->tm_mday == 0))
+               return -EINVAL;
+
+       if (tm->tm_mday > (days_in_mo[tm->tm_mon] + ((tm->tm_mon == 2) && leap_yr)))
+               return -EINVAL;
+
+       if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
+               return -EINVAL;
+
+       if ((tm->tm_year -= epoch) > 255)    /* They are unsigned */
+               return -EINVAL;
+
+       if (tm->tm_year > 169)
+               return -EINVAL;
+
+       if (tm->tm_year >= 100)
+               tm->tm_year -= 100;
+
+       BIN_TO_BCD(tm->tm_sec);
+       BIN_TO_BCD(tm->tm_min);
+       BIN_TO_BCD(tm->tm_hour);
+       BIN_TO_BCD(tm->tm_mday);
+       BIN_TO_BCD(tm->tm_mon);
+       BIN_TO_BCD(tm->tm_year);
+
+       return 0;
+}
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+                    unsigned long arg)
+{
+       struct rtc_time wtime; 
+       int status = 0;
+       u8 save_control;
+
+       switch (cmd) {
+       case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
+               mask_rtc_irq_bit(OMAP_RTC_INTERRUPTS_IT_ALARM);
+               break;
+       case RTC_AIE_ON:        /* Allow alarm interrupts.      */
+               set_rtc_irq_bit(OMAP_RTC_INTERRUPTS_IT_ALARM);
+               break;
+       case RTC_UIE_OFF:       /* Mask ints from RTC updates.  */
+               mask_rtc_irq_bit(OMAP_RTC_INTERRUPTS_IT_TIMER);
+               break;
+       case RTC_UIE_ON:        /* Allow ints for RTC updates.  */
+               set_rtc_irq_bit(OMAP_RTC_INTERRUPTS_IT_TIMER);
+               break;
+       case RTC_ALM_READ:      /* Read the present alarm time */
+               /*
+                * This returns a struct rtc_time. Reading >= 0xc0
+                * means "don't care" or "match all". Only the tm_hour,
+                * tm_min, and tm_sec values are filled in.
+                */
+               memset(&wtime, 0, sizeof(struct rtc_time));
+               get_rtc_alm_time(&wtime);
+               goto return_wtime;
+       case RTC_ALM_SET:       /* Store a time into the alarm */
+               status = utm2bcd((void __user *)arg, &wtime);
+               if (status != 0)
+                       return status;
+
+               spin_lock_irq(&rtc_lock);
+               CMOS_WRITE(wtime.tm_year, OMAP_RTC_ALARM_YEARS_REG);
+               CMOS_WRITE(wtime.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
+               CMOS_WRITE(wtime.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
+               CMOS_WRITE(wtime.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
+               CMOS_WRITE(wtime.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
+               CMOS_WRITE(wtime.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
+               spin_unlock_irq(&rtc_lock);
+
+               break;
+       case RTC_RD_TIME:       /* Read the time/date from RTC  */
+               memset(&wtime, 0, sizeof(struct rtc_time));
+               get_rtc_time(&wtime);
+               goto return_wtime;
+       case RTC_SET_TIME:      /* Set the RTC */
+               if (!capable(CAP_SYS_TIME))
+                       return -EACCES;
+
+               status = utm2bcd((void __user *)arg, &wtime);
+               if (status != 0)
+                       return status;
+
+               spin_lock_irq(&rtc_lock);
+               save_control = CMOS_READ(OMAP_RTC_CTRL_REG);
+               CMOS_WRITE((save_control & ~OMAP_RTC_CTRL_STOP),
+                          OMAP_RTC_CTRL_REG);
+               CMOS_WRITE(wtime.tm_year, OMAP_RTC_YEARS_REG);
+               CMOS_WRITE(wtime.tm_mon, OMAP_RTC_MONTHS_REG);
+               CMOS_WRITE(wtime.tm_mday, OMAP_RTC_DAYS_REG);
+               CMOS_WRITE(wtime.tm_hour, OMAP_RTC_HOURS_REG);
+               CMOS_WRITE(wtime.tm_min, OMAP_RTC_MINUTES_REG);
+               CMOS_WRITE(wtime.tm_sec, OMAP_RTC_SECONDS_REG);
+               CMOS_WRITE((save_control | OMAP_RTC_CTRL_STOP),
+                          OMAP_RTC_CTRL_REG);
+               spin_unlock_irq(&rtc_lock);
+
+               break;
+       case RTC_EPOCH_READ:    /* Read the epoch.      */
+               status = put_user (epoch, (unsigned long  __user *)arg);
+               break;
+       case RTC_EPOCH_SET:     /* Set the epoch.       */
+               if (!capable(CAP_SYS_TIME))
+                       return -EACCES;
+
+               /* 
+                * There were no RTC clocks before 1900.
+                */
+               if (arg < 1900)
+                       status = -EINVAL;
+               else
+                       epoch = arg;
+               break;
+       default:
+               status = -ENOTTY;
+       }
+       return status;
+
+return_wtime:
+       return copy_to_user((void  __user *)arg, &wtime, sizeof wtime)
+               ? -EFAULT
+               : 0;
+}
+
+/*
+ *     We enforce only one user at a time here with the open/close.
+ *     Also clear the previous interrupt data on an open, and clean
+ *     up things on a close.
+ */
+
+/* We use rtc_lock to protect against concurrent opens. So the BKL is not
+ * needed here. Or anywhere else in this driver. */
+static int rtc_open(struct inode *inode, struct file *file)
+{
+       spin_lock_irq (&rtc_lock);
+
+       if (rtc_status & RTC_IS_OPEN)
+               goto out_busy;
+
+       rtc_status |= RTC_IS_OPEN;
+
+       rtc_irq_data = 0;
+       spin_unlock_irq (&rtc_lock);
+       return 0;
+
+out_busy:
+       spin_unlock_irq (&rtc_lock);
+       return -EBUSY;
+}
+
+static int rtc_fasync(int fd, struct file *filp, int on)
+{
+       return fasync_helper (fd, filp, on, &rtc_async_queue);
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+       unsigned char tmp;
+
+       /*
+        * Turn off all interrupts once the device is no longer
+        * in use, and clear the data.
+        */
+
+       spin_lock_irq(&rtc_lock);
+       tmp = CMOS_READ(OMAP_RTC_INTERRUPTS_REG);
+       tmp &=  ~OMAP_RTC_INTERRUPTS_IT_ALARM;
+       tmp &=  ~OMAP_RTC_INTERRUPTS_IT_TIMER;
+       CMOS_WRITE(tmp, OMAP_RTC_INTERRUPTS_REG);
+       spin_unlock_irq(&rtc_lock);
+
+       if (file->f_flags & FASYNC) {
+               rtc_fasync (-1, file, 0);
+       }
+
+       spin_lock_irq (&rtc_lock);
+       rtc_irq_data = 0;
+       spin_unlock_irq (&rtc_lock);
+
+       /* No need for locking -- nobody else can do anything until this rmw
+        * is committed, and we don't implement timer support in omap-rtc.
+        */
+       rtc_status &= ~RTC_IS_OPEN;
+       return 0;
+}
+
+/* Called without the kernel lock - fine */
+static unsigned int rtc_poll(struct file *file, poll_table *wait)
+{
+       unsigned long l;
+
+       poll_wait(file, &rtc_wait, wait);
+
+       spin_lock_irq (&rtc_lock);
+       l = rtc_irq_data;
+       spin_unlock_irq (&rtc_lock);
+
+       if (l != 0)
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+/*
+ *     The various file operations we support.
+ */
+
+static struct file_operations rtc_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = rtc_read,
+       .poll           = rtc_poll,
+       .ioctl          = rtc_ioctl,
+       .open           = rtc_open,
+       .release        = rtc_release,
+       .fasync         = rtc_fasync,
+};
+
+static struct miscdevice rtc_dev = {
+       .minor          = RTC_MINOR,
+       .name           = "rtc",
+       .fops           = &rtc_fops,
+};
+
+static int __init omap_rtc_probe(struct device *dev)
+{
+       struct platform_device  *pdev = to_platform_device(dev);
+       struct resource         *res, *mem;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res)
+               mem = request_mem_region(res->start,
+                               res->end - res->start + 1,
+                               pdev->name);
+       else
+               mem = NULL;
+       if (!mem) {
+               pr_debug("%s: RTC registers at %x are not free.\n",
+                       pdev->name, OMAP_RTC_BASE);
+               return -EBUSY;
+       }
+       dev_set_drvdata(dev, mem);
+
+       if (CMOS_READ(OMAP_RTC_STATUS_REG) & OMAP_RTC_STATUS_POWER_UP) {
+               pr_info("%s: RTC power up reset detected.\n",
+                       pdev->name);
+               /* Clear OMAP_RTC_STATUS_POWER_UP */
+               CMOS_WRITE(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG);
+       }
+
+       if (CMOS_READ(OMAP_RTC_STATUS_REG) & OMAP_RTC_STATUS_ALARM) {
+               pr_debug("%s: Clearing RTC ALARM interrupt.\n",
+                       pdev->name);
+               /* Clear OMAP_RTC_STATUS_ALARM */
+               CMOS_WRITE(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+       }
+
+       if (request_irq(INT_RTC_TIMER, rtc_interrupt, SA_INTERRUPT,
+                       pdev->name, NULL)) {
+               pr_debug("%s: RTC timer interrupt IRQ%d is not free.\n",
+                       pdev->name, INT_RTC_TIMER);
+               goto fail;
+       }
+
+       if (request_irq(INT_RTC_ALARM, rtc_interrupt, SA_INTERRUPT,
+                       pdev->name, NULL)) {
+               pr_debug("%s: RTC alarm interrupt IRQ%d is not free.\n",
+                       pdev->name, INT_RTC_ALARM);
+               free_irq(INT_RTC_TIMER, NULL);
+               goto fail;
+       }
+
+       /* On boards with split power, RTC_ON_NOFF resets all but the RTC */
+       if (!(CMOS_READ(OMAP_RTC_CTRL_REG) & OMAP_RTC_CTRL_STOP)) {
+               pr_info("%s: Enabling RTC.\n", pdev->name);
+               CMOS_WRITE(OMAP_RTC_CTRL_STOP, OMAP_RTC_CTRL_REG);
+       } else
+               pr_info("%s: RTC already running.\n", pdev->name);
+
+       spin_lock_init(&rtc_lock);
+       misc_register(&rtc_dev);
+       create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL);
+
+       return 0;
+
+fail:
+       release_resource(mem);
+       return -EIO;
+}
+
+static int __exit omap_rtc_remove(struct device *dev)
+{
+       free_irq (INT_RTC_TIMER, NULL);
+       free_irq (INT_RTC_ALARM, NULL);
+
+       remove_proc_entry ("driver/rtc", NULL);
+       misc_deregister(&rtc_dev);
+
+       release_resource(dev_get_drvdata(dev));
+       return 0;
+}
+
+/*
+ *     Info exported via "/proc/driver/rtc".
+ */
+
+static int rtc_proc_output (char *buf)
+{
+#define YN(value) ((value) ? "yes" : "no")
+       char *p;
+       struct rtc_time tm;
+
+       p = buf;
+
+       get_rtc_time(&tm);
+
+       /*
+        * There is no way to tell if the luser has the RTC set for local
+        * time or for Universal Standard Time (GMT). Probably local though.
+        */
+       p += sprintf(p,
+                    "rtc_time\t: %02d:%02d:%02d\n"
+                    "rtc_date\t: %04d-%02d-%02d\n"
+                    "rtc_epoch\t: %04lu\n",
+                    tm.tm_hour, tm.tm_min, tm.tm_sec,
+                    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
+
+       get_rtc_alm_time(&tm);
+
+       /*
+        * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will
+        * match any value for that particular field. Values that are
+        * greater than a valid time, but less than 0xc0 shouldn't appear.
+        */
+       p += sprintf(p,
+                    "alarm_time\t: %02d:%02d:%02d\n"
+                    "alarm_date\t: %04d-%02d-%02d\n",
+                    tm.tm_hour, tm.tm_min, tm.tm_sec,
+                    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+
+       p += sprintf(p,
+                    "BCD\t\t: %s\n"
+                    "24hr\t\t: %s\n"
+                    "alarm_IRQ\t: %s\n"
+                    "update_IRQ\t: %s\n"
+                    "update_rate\t: %ud\n",
+                    YN(1),
+                    YN(1),
+                    YN(CMOS_READ(OMAP_RTC_INTERRUPTS_REG) &
+                       OMAP_RTC_INTERRUPTS_IT_ALARM),
+                    YN(CMOS_READ(OMAP_RTC_INTERRUPTS_REG) &
+                       OMAP_RTC_INTERRUPTS_IT_TIMER),
+                    CMOS_READ(OMAP_RTC_INTERRUPTS_REG) & 3 /* REVISIT */);
+
+       return  p - buf;
+#undef YN
+}
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+                         int count, int *eof, void *data)
+{
+        int len = rtc_proc_output (page);
+
+       if (len <= off+count)
+               *eof = 1;
+        *start = page + off;
+        len -= off;
+       if (len > count)
+               len = count;
+       if (len < 0)
+               len = 0;
+        return len;
+}
+
+/*
+ * Returns true if a clock update is in progress
+ */
+static inline unsigned char rtc_is_updating(void)
+{
+       unsigned char uip;
+
+       spin_lock_irq(&rtc_lock);
+       uip = (CMOS_READ(OMAP_RTC_STATUS_REG) & OMAP_RTC_STATUS_BUSY);
+       spin_unlock_irq(&rtc_lock);
+       return uip;
+}
+
+static void bcd2tm(struct rtc_time *tm)
+{
+       BCD_TO_BIN(tm->tm_sec);
+       BCD_TO_BIN(tm->tm_min);
+       BCD_TO_BIN(tm->tm_hour);
+       BCD_TO_BIN(tm->tm_mday);
+       BCD_TO_BIN(tm->tm_mon);
+       BCD_TO_BIN(tm->tm_year);
+
+       /*
+        * Account for differences between how the RTC uses the values
+        * and how they are defined in a struct rtc_time;
+        */
+       if ((tm->tm_year += (epoch - 1900)) <= 69)
+               tm->tm_year += 100;
+
+       tm->tm_mon--;
+}
+
+
+static void get_rtc_time(struct rtc_time *rtc_tm)
+{
+       unsigned char ctrl;
+
+       /* REVISIT: Fix this comment!!!
+        * read RTC once any update in progress is done. The update
+        * can take just over 2ms. We wait 10 to 20ms. There is no need to
+        * to poll-wait (up to 1s - eeccch) for the falling edge of OMAP_RTC_STATUS_BUSY.
+        * If you need to know *exactly* when a second has started, enable
+        * periodic update complete interrupts, (via ioctl) and then 
+        * immediately read /dev/rtc which will block until you get the IRQ.
+        * Once the read clears, read the RTC time (again via ioctl). Easy.
+        */
+
+#if    0 /* REVISIT: This need to do as the TRM says. */
+       unsigned long uip_watchdog = jiffies;
+       if (rtc_is_updating() != 0)
+               while (jiffies - uip_watchdog < 2*HZ/100) {
+                       barrier();
+                       cpu_relax();
+               }
+#endif
+
+       /*
+        * Only the values that we read from the RTC are set. We leave
+        * tm_wday, tm_yday and tm_isdst untouched. Even though the
+        * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+        * by the RTC when initially set to a non-zero value.
+        */
+       spin_lock_irq(&rtc_lock);
+       rtc_tm->tm_sec = CMOS_READ(OMAP_RTC_SECONDS_REG);
+       rtc_tm->tm_min = CMOS_READ(OMAP_RTC_MINUTES_REG);
+       rtc_tm->tm_hour = CMOS_READ(OMAP_RTC_HOURS_REG);
+       rtc_tm->tm_mday = CMOS_READ(OMAP_RTC_DAYS_REG);
+       rtc_tm->tm_mon = CMOS_READ(OMAP_RTC_MONTHS_REG);
+       rtc_tm->tm_year = CMOS_READ(OMAP_RTC_YEARS_REG);
+       ctrl = CMOS_READ(OMAP_RTC_CTRL_REG);
+       spin_unlock_irq(&rtc_lock);
+
+       bcd2tm(rtc_tm);
+}
+
+static void get_rtc_alm_time(struct rtc_time *alm_tm)
+{
+       unsigned char ctrl;
+
+       spin_lock_irq(&rtc_lock);
+       alm_tm->tm_sec = CMOS_READ(OMAP_RTC_ALARM_SECONDS_REG);
+       alm_tm->tm_min = CMOS_READ(OMAP_RTC_ALARM_MINUTES_REG);
+       alm_tm->tm_hour = CMOS_READ(OMAP_RTC_ALARM_HOURS_REG);
+       alm_tm->tm_mday = CMOS_READ(OMAP_RTC_ALARM_DAYS_REG);
+       alm_tm->tm_mon = CMOS_READ(OMAP_RTC_ALARM_MONTHS_REG);
+       alm_tm->tm_year = CMOS_READ(OMAP_RTC_ALARM_YEARS_REG);
+       ctrl = CMOS_READ(OMAP_RTC_CTRL_REG);
+       spin_unlock_irq(&rtc_lock);
+
+       bcd2tm(alm_tm);
+}
+
+/*
+ * Used to disable/enable UIE and AIE interrupts.
+ */
+
+static void mask_rtc_irq_bit(unsigned char bit)
+{
+       unsigned char val;
+
+       spin_lock_irq(&rtc_lock);
+       val = CMOS_READ(OMAP_RTC_INTERRUPTS_REG);
+       val &=  ~bit;
+       CMOS_WRITE(val, OMAP_RTC_INTERRUPTS_REG);
+       rtc_irq_data = 0;
+       spin_unlock_irq(&rtc_lock);
+}
+
+static void set_rtc_irq_bit(unsigned char bit)
+{
+       unsigned char val;
+
+       spin_lock_irq(&rtc_lock);
+       val = CMOS_READ(OMAP_RTC_INTERRUPTS_REG);
+       val |= bit;
+       CMOS_WRITE(val, OMAP_RTC_INTERRUPTS_REG);
+       rtc_irq_data = 0;
+       spin_unlock_irq(&rtc_lock);
+}
+
+#ifdef CONFIG_PM
+static struct timespec rtc_delta;
+
+static int rtc_suspend(struct device *dev, pm_message_t state)
+{
+       struct rtc_time rtc_tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+       get_rtc_time(&rtc_tm);
+       rtc_tm_to_time(&rtc_tm, &time.tv_sec);
+
+       save_time_delta(&rtc_delta, &time);
+
+       return 0;
+}
+
+static int rtc_resume(struct device *dev)
+{
+       struct rtc_time rtc_tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+       get_rtc_time(&rtc_tm);
+       rtc_tm_to_time(&rtc_tm, &time.tv_sec);
+
+       restore_time_delta(&rtc_delta, &time);
+
+       return 0;
+}
+#else
+#define rtc_suspend NULL
+#define rtc_resume  NULL
+#endif
+
+static struct device_driver omap_rtc_driver = {
+       .name           = "omap_rtc",
+       .bus            = &platform_bus_type,
+       .probe          = omap_rtc_probe,
+       .remove         = __exit_p(omap_rtc_remove),
+       .suspend        = rtc_suspend,
+       .resume         = rtc_resume,
+};
+
+static int __init rtc_init(void)
+{
+       return driver_register(&omap_rtc_driver);
+}
+
+static void __exit rtc_exit(void)
+{
+       driver_unregister(&omap_rtc_driver);
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
+
+MODULE_AUTHOR("George G. Davis (and others)");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(RTC_MINOR);
diff --git a/drivers/char/omap-rtc.h b/drivers/char/omap-rtc.h
new file mode 100644 (file)
index 0000000..d8acb56
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  TI OMAP Real Time Clock header file
+ *
+ *  Copyright (C) 2003 TI
+ *
+ *  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.
+ *
+ */
+
+#define OMAP_RTC_BASE                  0xfffb4800
+#define OMAP_RTC_SIZE                  128
+
+#define OMAP_RTC_VIRT_BASE             IO_ADDRESS(OMAP_RTC_BASE)
+
+/*
+ * Real-Time Clock
+ */
+
+#define OMAP_RTC_SECONDS_REG            (OMAP_RTC_BASE + 0x00)
+#define OMAP_RTC_MINUTES_REG            (OMAP_RTC_BASE + 0x04)
+#define OMAP_RTC_HOURS_REG              (OMAP_RTC_BASE + 0x08)
+#define OMAP_RTC_DAYS_REG               (OMAP_RTC_BASE + 0x0C)
+#define OMAP_RTC_MONTHS_REG             (OMAP_RTC_BASE + 0x10)
+#define OMAP_RTC_YEARS_REG              (OMAP_RTC_BASE + 0x14)
+#define OMAP_RTC_WEEKS_REG              (OMAP_RTC_BASE + 0x18)
+#define OMAP_RTC_ALARM_SECONDS_REG      (OMAP_RTC_BASE + 0x20)
+#define OMAP_RTC_ALARM_MINUTES_REG      (OMAP_RTC_BASE + 0x24)
+#define OMAP_RTC_ALARM_HOURS_REG        (OMAP_RTC_BASE + 0x28)
+#define OMAP_RTC_ALARM_DAYS_REG         (OMAP_RTC_BASE + 0x2c)
+#define OMAP_RTC_ALARM_MONTHS_REG       (OMAP_RTC_BASE + 0x30)
+#define OMAP_RTC_ALARM_YEARS_REG        (OMAP_RTC_BASE + 0x34)
+#define OMAP_RTC_CTRL_REG               (OMAP_RTC_BASE + 0x40)
+#define OMAP_RTC_STATUS_REG             (OMAP_RTC_BASE + 0x44)
+#define OMAP_RTC_INTERRUPTS_REG         (OMAP_RTC_BASE + 0x48)
+#define OMAP_RTC_COMP_LSB_REG           (OMAP_RTC_BASE + 0x4c)
+#define OMAP_RTC_COMP_MSB_REG           (OMAP_RTC_BASE + 0x50)
+
+/* RTC Control Register bit fields: */
+
+#define OMAP_RTC_CTRL_STOP              (1<<0)
+
+/* RTC Status Register bit fields: */
+
+#define OMAP_RTC_STATUS_POWER_UP        (1<<7)
+#define OMAP_RTC_STATUS_ALARM           (1<<6)
+#define OMAP_RTC_STATUS_1D_EVENT        (1<<5)
+#define OMAP_RTC_STATUS_1H_EVENT        (1<<4)
+#define OMAP_RTC_STATUS_1M_EVENT        (1<<3)
+#define OMAP_RTC_STATUS_1S_EVENT        (1<<2)
+#define OMAP_RTC_STATUS_RUN             (1<<1)
+#define OMAP_RTC_STATUS_BUSY            (1<<0)
+
+/* RTC Interrupt Register bit fields: */
+
+#define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
+#define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
index 344001b45af94b3caa8ac0cf83979e224bb61e96..7e1594894a1cd99564aa039f0c31f107b5dcbfaf 100644 (file)
@@ -623,4 +623,11 @@ config USBPCWATCHDOG
 
          Most people will say N.
 
+config OMAP_WATCHDOG
+       tristate "OMAP Watchdog"
+       depends on WATCHDOG && (ARCH_OMAP16XX || ARCH_OMAP24XX)
+       help
+         Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog. Say 'Y' here to enable the
+         OMAP1610/OMAP1710 watchdog timer.
+
 endmenu
index cfd0a39877102224f901856f805562ed4feb1b33..2c2bd86c61d59d4581bcb6193d082ba53fb1eb69 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
+obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
 obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
 obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
new file mode 100644 (file)
index 0000000..2c28307
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * linux/drivers/char/omap_wdt.c
+ *
+ * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
+ *
+ * Author: MontaVista Software, Inc.
+ *      <gdavis@mvista.com> or <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * History:
+ *
+ * 20030527: George G. Davis <gdavis@mvista.com>
+ *     Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
+ *     (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *     Based on SoftDog driver by Alan Cox <alan@redhat.com>
+ *
+ * Copyright (c) 2004 Texas Instruments.
+ *     1. Modified to support OMAP1610 32-KHz watchdog timer
+ *     2. Ported to 2.6 kernel
+ *
+ * Copyright (c) 2005 David Brownell
+ *     Use the driver model and standard identifiers; handle bigger timeouts.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+#include <asm/hardware/clock.h>
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#include <asm/arch/prcm.h>
+#endif
+
+#include "omap_wdt.h"
+
+static unsigned timer_margin;
+module_param(timer_margin, uint, 0);
+MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
+
+static int omap_wdt_users;
+static struct clk *armwdt_ck = NULL;
+static struct clk *mpu_wdt_ick = NULL;
+static struct clk *mpu_wdt_fck = NULL;
+
+static unsigned int wdt_trgr_pattern = 0x1234;
+
+static void omap_wdt_ping(void)
+{
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) ;        /* wait for posted write to complete */
+       wdt_trgr_pattern = ~wdt_trgr_pattern;
+       omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) ;        /* wait for posted write to complete */
+       /* reloaded WCRR from WLDR */
+}
+
+static void omap_wdt_enable(void)
+{
+       /* Sequence to enable the watchdog */
+       omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) ;
+       omap_writel(0x4444, OMAP_WATCHDOG_SPR);
+       while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) ;
+}
+
+static void omap_wdt_disable(void)
+{
+       /* sequence required to disable watchdog */
+       omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) ;
+       omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) ;
+}
+
+static void omap_wdt_adjust_timeout(unsigned new_timeout)
+{
+       if (new_timeout < TIMER_MARGIN_MIN)
+               new_timeout = TIMER_MARGIN_DEFAULT;
+       if (new_timeout > TIMER_MARGIN_MAX)
+               new_timeout = TIMER_MARGIN_MAX;
+       timer_margin = new_timeout;
+}
+
+static void omap_wdt_set_timeout(void)
+{
+       u32 pre_margin = GET_WLDR_VAL(timer_margin);
+
+       /* just count up at 32 KHz */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+               continue;
+       omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+               continue;
+}
+
+/*
+ *     Allow only one task to hold it open
+ */
+
+static int omap_wdt_open(struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
+               return -EBUSY;
+
+       if (cpu_is_omap16xx()) {
+               clk_use(armwdt_ck);     /* Enable the clock */
+       }
+
+       if (cpu_is_omap24xx()) {
+               clk_use(mpu_wdt_ick);   /* Enable the interface clock */
+               clk_use(mpu_wdt_fck);   /* Enable the functional clock */
+       }
+
+       /* initialize prescaler */
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+               continue;
+       omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
+       while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+               continue;
+
+       omap_wdt_set_timeout();
+       omap_wdt_enable();
+       return 0;
+}
+
+static int omap_wdt_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer unless NOWAYOUT is defined.
+        */
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
+       omap_wdt_disable();
+
+       if (cpu_is_omap16xx()) {
+               clk_unuse(armwdt_ck);   /* Disable the clock */
+               clk_put(armwdt_ck);
+               armwdt_ck = NULL;
+       }
+
+       if (cpu_is_omap24xx()) {
+               clk_unuse(mpu_wdt_ick); /* Disable the clock */
+               clk_unuse(mpu_wdt_fck); /* Disable the clock */
+               clk_put(mpu_wdt_ick);
+               clk_put(mpu_wdt_fck);
+               mpu_wdt_ick = NULL;
+               mpu_wdt_fck = NULL;
+       }
+#else
+       printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
+#endif
+       omap_wdt_users = 0;
+       return 0;
+}
+
+static ssize_t
+omap_wdt_write(struct file *file, const char __user * data,
+       size_t len, loff_t * ppos)
+{
+       /* Refresh LOAD_TIME. */
+       if (len)
+               omap_wdt_ping();
+       return len;
+}
+
+static int
+omap_wdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int new_margin;
+       static struct watchdog_info ident = {
+               .identity = "OMAP Watchdog",
+               .options = WDIOF_SETTIMEOUT,
+               .firmware_version = 0,
+       };
+
+       switch (cmd) {
+       default:
+               return -ENOIOCTLCMD;
+       case WDIOC_GETSUPPORT:
+               return copy_to_user((struct watchdog_info __user *)arg, &ident,
+       sizeof(ident));
+       case WDIOC_GETSTATUS:
+               return put_user(0, (int __user *)arg);
+       case WDIOC_GETBOOTSTATUS:
+               if (cpu_is_omap16xx())
+                       return put_user(omap_readw(ARM_SYSST),
+                                       (int __user *)arg);
+               if (cpu_is_omap24xx())
+                       return put_user(RM_RSTST_WKUP, (int __user *)arg);
+       case WDIOC_KEEPALIVE:
+               omap_wdt_ping();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_margin, (int __user *)arg))
+                       return -EFAULT;
+               omap_wdt_adjust_timeout(new_margin);
+
+               omap_wdt_disable();
+               omap_wdt_set_timeout();
+               omap_wdt_enable();
+
+               omap_wdt_ping();
+               /* Fall */
+       case WDIOC_GETTIMEOUT:
+               return put_user(timer_margin, (int __user *)arg);
+       }
+}
+
+static struct file_operations omap_wdt_fops = {
+       .owner = THIS_MODULE,
+       .write = omap_wdt_write,
+       .ioctl = omap_wdt_ioctl,
+       .open = omap_wdt_open,
+       .release = omap_wdt_release,
+};
+
+static struct miscdevice omap_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name = "watchdog",
+       .fops = &omap_wdt_fops
+};
+
+static int __init omap_wdt_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct resource *res, *mem;
+       int ret;
+
+       /* reserve static register mappings */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       mem = request_mem_region(res->start, res->end - res->start + 1,
+                                pdev->name);
+       if (mem == NULL)
+               return -EBUSY;
+
+       dev_set_drvdata(dev, mem);
+
+       omap_wdt_users = 0;
+
+       if (cpu_is_omap16xx()) {
+               armwdt_ck = clk_get(dev, "armwdt_ck");
+               if (IS_ERR(armwdt_ck)) {
+                       ret = PTR_ERR(armwdt_ck);
+                       armwdt_ck = NULL;
+                       goto fail;
+               }
+       }
+
+       if (cpu_is_omap24xx()) {
+               mpu_wdt_ick = clk_get(dev, "mpu_wdt_ick");
+               if (IS_ERR(mpu_wdt_ick)) {
+                       ret = PTR_ERR(mpu_wdt_ick);
+                       mpu_wdt_ick = NULL;
+                       goto fail;
+               }
+               mpu_wdt_fck = clk_get(dev, "mpu_wdt_fck");
+               if (IS_ERR(mpu_wdt_fck)) {
+                       ret = PTR_ERR(mpu_wdt_fck);
+                       mpu_wdt_fck = NULL;
+                       goto fail;
+               }
+       }
+
+       omap_wdt_disable();
+       omap_wdt_adjust_timeout(timer_margin);
+
+       omap_wdt_miscdev.dev = dev;
+       ret = misc_register(&omap_wdt_miscdev);
+       if (ret)
+               goto fail;
+
+       pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
+
+       /* autogate OCP interface clock */
+       omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
+       return 0;
+
+fail:
+       if (armwdt_ck)
+               clk_put(armwdt_ck);
+       if (mpu_wdt_ick)
+               clk_put(mpu_wdt_ick);
+       if (mpu_wdt_fck)
+               clk_put(mpu_wdt_fck);
+       release_resource(mem);
+       return ret;
+}
+
+static void omap_wdt_shutdown(struct device *dev)
+{
+       omap_wdt_disable();
+}
+
+static int __exit omap_wdt_remove(struct device *dev)
+{
+       struct resource *mem = dev_get_drvdata(dev);
+       misc_deregister(&omap_wdt_miscdev);
+       release_resource(mem);
+       if (armwdt_ck)
+               clk_put(armwdt_ck);
+       if (mpu_wdt_ick)
+               clk_put(mpu_wdt_ick);
+       if (mpu_wdt_fck)
+               clk_put(mpu_wdt_fck);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* REVISIT ... not clear this is the best way to handle system suspend; and
+ * it's very inappropriate for selective device suspend (e.g. suspending this
+ * through sysfs rather than by stopping the watchdog daemon).  Also, this
+ * may not play well enough with NOWAYOUT...
+ */
+
+static int omap_wdt_suspend(struct device *dev, pm_message_t state)
+{
+       if (omap_wdt_users)
+               omap_wdt_disable();
+       return 0;
+}
+
+static int omap_wdt_resume(struct device *dev)
+{
+       if (omap_wdt_users) {
+               omap_wdt_enable();
+               omap_wdt_ping();
+       }
+       return 0;
+}
+
+#else
+#define        omap_wdt_suspend        NULL
+#define        omap_wdt_resume         NULL
+#endif
+
+static struct device_driver omap_wdt_driver = {
+       .name = "omap_wdt",
+       .bus = &platform_bus_type,
+       .probe = omap_wdt_probe,
+       .shutdown = omap_wdt_shutdown,
+       .remove = __exit_p(omap_wdt_remove),
+       .suspend = omap_wdt_suspend,
+       .resume = omap_wdt_resume,
+};
+
+static int __init omap_wdt_init(void)
+{
+       return driver_register(&omap_wdt_driver);
+}
+
+static void __exit omap_wdt_exit(void)
+{
+       driver_unregister(&omap_wdt_driver);
+}
+
+module_init(omap_wdt_init);
+module_exit(omap_wdt_exit);
+
+MODULE_AUTHOR("George G. Davis");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/omap_wdt.h b/drivers/char/watchdog/omap_wdt.h
new file mode 100644 (file)
index 0000000..52a532a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  linux/drivers/char/watchdog/omap_wdt.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      OMAP Watchdog timer register definitions
+ *
+ *  Copyright (C) 2004 Texas Instruments.
+ *
+ *  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 _OMAP_WATCHDOG_H
+#define _OMAP_WATCHDOG_H
+
+#define OMAP1610_WATCHDOG_BASE         0xfffeb000
+#define OMAP2420_WATCHDOG_BASE         0x48022000      /*WDT Timer 2 */
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP_WATCHDOG_BASE             OMAP2420_WATCHDOG_BASE
+#else
+#define OMAP_WATCHDOG_BASE             OMAP1610_WATCHDOG_BASE
+#define RM_RSTST_WKUP                  0
+#endif
+
+#define OMAP_WATCHDOG_REV              (OMAP_WATCHDOG_BASE + 0x00)
+#define OMAP_WATCHDOG_SYS_CONFIG       (OMAP_WATCHDOG_BASE + 0x10)
+#define OMAP_WATCHDOG_STATUS           (OMAP_WATCHDOG_BASE + 0x14)
+#define OMAP_WATCHDOG_CNTRL            (OMAP_WATCHDOG_BASE + 0x24)
+#define OMAP_WATCHDOG_CRR              (OMAP_WATCHDOG_BASE + 0x28)
+#define OMAP_WATCHDOG_LDR              (OMAP_WATCHDOG_BASE + 0x2c)
+#define OMAP_WATCHDOG_TGR              (OMAP_WATCHDOG_BASE + 0x30)
+#define OMAP_WATCHDOG_WPS              (OMAP_WATCHDOG_BASE + 0x34)
+#define OMAP_WATCHDOG_SPR              (OMAP_WATCHDOG_BASE + 0x48)
+
+/* Using the prescaler, the OMAP watchdog could go for many
+ * months before firing.  These limits work without scaling,
+ * with the 60 second default assumed by most tools and docs.
+ */
+#define TIMER_MARGIN_MAX       (24 * 60 * 60)  /* 1 day */
+#define TIMER_MARGIN_DEFAULT   60      /* 60 secs */
+#define TIMER_MARGIN_MIN       1
+
+#define PTV                    0       /* prescale */
+#define GET_WLDR_VAL(secs)     (0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
+
+#endif                         /* _OMAP_WATCHDOG_H */
index 24383afdda76d4c446445381b91482e0a9938f2b..8105b07e2adee192ed3999ccd15ffa84ca6dbf0f 100644 (file)
@@ -6,6 +6,7 @@ menu "I2C support"
 
 config I2C
        tristate "I2C support"
+       default y if MACH_OMAP_H3 || MACH_OMAP_OSK
        ---help---
          I2C (pronounce: I-square-C) is a slow serial bus protocol used in
          many micro controller applications and developed by Philips.  SMBus,
index 4010fe92e72b637f6c138813a82c15c744b79ba3..4b6721288568a7ed46fc1b24189312b521ede1cd 100644 (file)
@@ -520,4 +520,11 @@ config I2C_MV64XXX
          This driver can also be built as a module.  If so, the module
          will be called i2c-mv64xxx.
 
+config I2C_OMAP
+       tristate "OMAP I2C adapter"
+       depends on I2C && ARCH_OMAP
+       default y if MACH_OMAP_H3 || MACH_OMAP_OSK
+       help
+         Support for TI OMAP I2C driver. Say yes if you want to use the OMAP
+         I2C interface.
 endmenu
index f1df00f66c6cde856f188126fa1e4ab3a4ea2a5d..e488ad190411ca7f5facc2f7757dd44a25acccfd 100644 (file)
@@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_VIAPRO)      += i2c-viapro.o
 obj-$(CONFIG_I2C_VOODOO3)      += i2c-voodoo3.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
+obj-$(CONFIG_I2C_OMAP)          += i2c-omap.o
 
 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
new file mode 100644 (file)
index 0000000..826b10c
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * linux/drivers/i2c/i2c-omap.c
+ *
+ * TI OMAP I2C master mode driver
+ *
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Updated to work with multiple I2C interfaces on 24xx by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * ----------------------------------------------------------------------------
+ * This file was highly leveraged from i2c-elektor.c:
+ *
+ * Copyright 1995-97 Simon G. Vogl
+ *           1998-99 Hans Berglund
+ *
+ * With some changes from Kysti M�kki <kmalkki@cc.hut.fi> and even
+ * Frodo Looijaard <frodol@dds.nl>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+/* ----- global defines ----------------------------------------------- */
+static const char driver_name[] = "i2c_omap";
+
+#define MODULE_NAME "OMAP I2C"
+#define OMAP_I2C_TIMEOUT (1*HZ)        /* timeout waiting for an I2C transaction */
+
+#define pr_err(format, arg...) \
+               printk(KERN_ERR MODULE_NAME " ERROR: " format "\n", ## arg )
+
+#define DEFAULT_OWN            1       /* default own I2C address */
+#define MAX_MESSAGES           65536   /* max number of messages */
+
+#define OMAP_I2C_REV           0x00
+#define OMAP_I2C_IE            0x04
+#define OMAP_I2C_STAT          0x08
+#define OMAP_I2C_IV            0x0c
+#define OMAP_I2C_SYSS          0x10
+#define OMAP_I2C_BUF           0x14
+#define OMAP_I2C_CNT           0x18
+#define OMAP_I2C_DATA          0x1c
+#define OMAP_I2C_SYSC          0x20
+#define OMAP_I2C_CON           0x24
+#define OMAP_I2C_OA            0x28
+#define OMAP_I2C_SA            0x2c
+#define OMAP_I2C_PSC           0x30
+#define OMAP_I2C_SCLL          0x34
+#define OMAP_I2C_SCLH          0x38
+#define OMAP_I2C_SYSTEST       0x3c
+
+/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XRDY_IE    (1 << 4)        /* TX data ready int enable */
+#define OMAP_I2C_IE_RRDY_IE    (1 << 3)        /* RX data ready int enable */
+#define OMAP_I2C_IE_ARDY_IE    (1 << 2)        /* Access ready int enable */
+#define OMAP_I2C_IE_NACK_IE    (1 << 1)        /* No ack interrupt enable */
+#define OMAP_I2C_IE_AL_IE      (1 << 0)        /* Arbitration lost int ena */
+
+/* I2C Status Register (OMAP_I2C_STAT): */
+#define OMAP_I2C_STAT_SBD      (1 << 15)       /* Single byte data */
+#define OMAP_I2C_STAT_BB       (1 << 12)       /* Bus busy */
+#define OMAP_I2C_STAT_ROVR     (1 << 11)       /* Receive overrun */
+#define OMAP_I2C_STAT_XUDF     (1 << 10)       /* Transmit underflow */
+#define OMAP_I2C_STAT_AAS      (1 << 9)        /* Address as slave */
+#define OMAP_I2C_STAT_AD0      (1 << 8)        /* Address zero */
+#define OMAP_I2C_STAT_XRDY     (1 << 4)        /* Transmit data ready */
+#define OMAP_I2C_STAT_RRDY     (1 << 3)        /* Receive data ready */
+#define OMAP_I2C_STAT_ARDY     (1 << 2)        /* Register access ready */
+#define OMAP_I2C_STAT_NACK     (1 << 1)        /* No ack interrupt enable */
+#define OMAP_I2C_STAT_AL       (1 << 0)        /* Arbitration lost int ena */
+
+/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
+#define OMAP_I2C_BUF_RDMA_EN   (1 << 15)       /* RX DMA channel enable */
+#define OMAP_I2C_BUF_XDMA_EN   (1 << 7)        /* TX DMA channel enable */
+
+/* I2C Configuration Register (OMAP_I2C_CON): */
+#define OMAP_I2C_CON_EN                (1 << 15)       /* I2C module enable */
+#define OMAP_I2C_CON_RST       (0 << 15)       /* I2C module reset */
+#define OMAP_I2C_CON_BE                (1 << 14)       /* Big endian mode */
+#define OMAP_I2C_CON_STB       (1 << 11)       /* Start byte mode (master) */
+#define OMAP_I2C_CON_MST       (1 << 10)       /* Master/slave mode */
+#define OMAP_I2C_CON_TRX       (1 << 9)        /* TX/RX mode (master only) */
+#define OMAP_I2C_CON_XA                (1 << 8)        /* Expand address */
+#define OMAP_I2C_CON_RM                (1 << 2)        /* Repeat mode (master only) */
+#define OMAP_I2C_CON_STP       (1 << 1)        /* Stop cond (master only) */
+#define OMAP_I2C_CON_STT       (1 << 0)        /* Start condition (master) */
+
+/* I2C System Test Register (OMAP_I2C_SYSTEST): */
+#define OMAP_I2C_SYSTEST_ST_EN         (1 << 15)       /* System test enable */
+#define OMAP_I2C_SYSTEST_FREE          (1 << 14)       /* Free running mode */
+#define OMAP_I2C_SYSTEST_TMODE_MASK    (3 << 12)       /* Test mode select */
+#define OMAP_I2C_SYSTEST_TMODE_SHIFT   (12)            /* Test mode select */
+#define OMAP_I2C_SYSTEST_SCL_I         (1 << 3)        /* SCL line sense in */
+#define OMAP_I2C_SYSTEST_SCL_O         (1 << 2)        /* SCL line drive out */
+#define OMAP_I2C_SYSTEST_SDA_I         (1 << 1)        /* SDA line sense in */
+#define OMAP_I2C_SYSTEST_SDA_O         (1 << 0)        /* SDA line drive out */
+
+/* I2C System Status register (OMAP_I2C_SYSS): */
+#define OMAP_I2C_SYSS_RDONE            1               /* Reset Done */
+
+/* I2C System Configuration Register (OMAP_I2C_SYSC): */
+#define OMAP_I2C_SYSC_SRST             (1 << 1)        /* Soft Reset */
+
+/* ------- debugging ---------------------------------------------------*/
+
+#define I2C_OMAP_DEBUG
+#ifdef I2c_OMAP_DEBUG
+static int i2c_debug;
+
+module_param(i2c_debug, int, 0);
+MODULE_PARM_DESC(i2c_debug,
+               "debug level - 0 off; 1 normal; 2,3 more verbose; "
+               "9 omap-protocol");
+
+#define DEB(level, format, arg...) do { \
+       if (i2c_debug >= level) \
+               printk(KERN_DEBUG MODULE_NAME " DEBUG: " format "\n", ## arg); \
+       } while(0)
+
+#define DEB0(format, arg...) DEB(0, format, arg)
+#define DEB1(format, arg...) DEB(1, format, arg)
+#define DEB2(format, arg...) DEB(2, format, arg)
+#define DEB3(format, arg...) DEB(3, format, arg)
+#define DEB9(format, arg...) DEB(9, format, arg)
+
+#else
+
+#define DEB0(fmt, args...)
+#define DEB1(fmt, args...)
+#define DEB2(fmt, args...)
+#define DEB3(fmt, args...)
+#define DEB9(fmt, args...)
+
+#endif
+
+static int clock = 100;        /* Default: Fast Mode = 400 KHz, Standard = 100 KHz */
+module_param(clock, int, 0);
+MODULE_PARM_DESC(clock, "Set I2C clock in KHz: 100 or 400 (Fast Mode)");
+
+static int own;
+module_param(own, int, 0);
+MODULE_PARM_DESC(own, "Address of OMAP i2c master (0 for default == 1)");
+
+struct omap_i2c_dev {
+       struct device           *dev;
+       void __iomem            *base;          /* virtual */
+       int                     irq;
+       struct clk              *iclk;          /* Interface clock */
+       struct clk              *fclk;          /* Functional clock */
+       int                     cmd_complete, cmd_err;
+       wait_queue_head_t       cmd_wait;
+       u8                      *buf;
+       size_t                  buf_len;
+       struct i2c_adapter      adapter;
+       int                     rev1;
+};
+
+static void inline omap_i2c_write(struct omap_i2c_dev *i2c_dev,
+                                 int val, int reg)
+{
+       __raw_writew(val, i2c_dev->base + reg);
+}
+
+static int inline omap_i2c_read(struct omap_i2c_dev *i2c_dev, int reg)
+{
+       return __raw_readw(i2c_dev->base + reg);
+}
+
+static void omap_i2c_reset(struct omap_i2c_dev *omap_i2c_dev)
+{
+       unsigned long timeout;
+       u16 psc = 0;
+       unsigned long fclk_rate;
+
+       /* Soft reset, hard reset needed only for rev1 */
+       if (!omap_i2c_dev->rev1)
+               omap_i2c_write(omap_i2c_dev, OMAP_I2C_SYSC_SRST, OMAP_I2C_SYSC);
+       else
+               omap_i2c_write(omap_i2c_dev, OMAP_I2C_CON_RST, OMAP_I2C_CON);
+
+       fclk_rate = 12000000;
+
+       if (!cpu_is_omap24xx()) {
+               struct clk *armxor_ck;
+               unsigned long armxor_rate;
+
+               armxor_ck = clk_get(NULL, "armxor_ck");
+               if (IS_ERR(armxor_ck)) {
+                       printk(KERN_WARNING "i2c: Could not get armxor_ck\n");
+                       armxor_rate = 12000000;
+               } else {
+                       armxor_rate = clk_get_rate(armxor_ck);
+                       clk_put(armxor_ck);
+               }
+
+               if (armxor_rate > 16000000)
+                       psc = (armxor_rate + 8000000) / 12000000;
+
+               fclk_rate = armxor_rate;
+       }
+
+       /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
+       omap_i2c_write(omap_i2c_dev, psc, OMAP_I2C_PSC);
+
+       /* Program desired operating rate */
+       fclk_rate /= (psc + 1) * 1000;
+       if (psc > 2)
+               psc = 2;
+       omap_i2c_write(omap_i2c_dev,
+                       fclk_rate / (clock * 2) - 7 + psc, OMAP_I2C_SCLL);
+       omap_i2c_write(omap_i2c_dev,
+                       fclk_rate / (clock * 2) - 7 + psc, OMAP_I2C_SCLH);
+
+       /* Set Own Address: */
+       omap_i2c_write(omap_i2c_dev, own, OMAP_I2C_OA);
+
+       /* Enable interrupts */
+       omap_i2c_write(omap_i2c_dev,
+                       (OMAP_I2C_IE_XRDY_IE | OMAP_I2C_IE_RRDY_IE |
+                        OMAP_I2C_IE_ARDY_IE | OMAP_I2C_IE_NACK_IE |
+                        OMAP_I2C_IE_AL_IE),
+                       OMAP_I2C_IE);
+
+       /* Take the I2C module out of reset: */
+       omap_i2c_write(omap_i2c_dev, OMAP_I2C_CON_EN, OMAP_I2C_CON);
+
+       if (!omap_i2c_dev->rev1){
+               timeout = jiffies + OMAP_I2C_TIMEOUT;
+               while (!(omap_i2c_read(omap_i2c_dev, OMAP_I2C_SYSS) &
+                                       OMAP_I2C_SYSS_RDONE)) {
+                       if (time_after(jiffies, timeout)) {
+                               pr_err("timeout waiting for I2C reset");
+                               break;
+                       }
+                       msleep(1);
+               }
+       }
+}
+
+/*
+ * Waiting on Bus Busy
+ */
+static int
+omap_i2c_wait_for_bb(struct omap_i2c_dev *omap_i2c_dev, char allow_sleep)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + OMAP_I2C_TIMEOUT;
+       while (omap_i2c_read(omap_i2c_dev, OMAP_I2C_STAT) & OMAP_I2C_STAT_BB) {
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_WARNING "timeout waiting for bus ready\n");
+                       return -ETIMEDOUT;
+               }
+               if (allow_sleep)
+                       msleep(1);
+       }
+
+       return 0;
+}
+
+/*
+ * Low level master read/write transaction.
+ */
+static int
+omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
+{
+       struct omap_i2c_dev *omap_i2c_dev = i2c_get_adapdata(adap);
+       u8 zero_byte = 0;
+       int r;
+       u16 w;
+
+       DEB2("addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
+            msg->addr, msg->len, msg->flags, stop);
+
+       omap_i2c_write(omap_i2c_dev, msg->addr, OMAP_I2C_SA);
+
+       /* Sigh, seems we can't do zero length transactions. Thus, we
+        * can't probe for devices w/o actually sending/receiving at least
+        * a single byte. So we'll set count to 1 for the zero length
+        * transaction case and hope we don't cause grief for some
+        * arbitrary device due to random byte write/read during
+        * probes.
+        */
+       if (msg->len == 0) {
+               omap_i2c_dev->buf = &zero_byte;
+               omap_i2c_dev->buf_len = 1;
+       } else {
+               omap_i2c_dev->buf = msg->buf;
+               omap_i2c_dev->buf_len = msg->len;
+       }
+       omap_i2c_write(omap_i2c_dev, omap_i2c_dev->buf_len, OMAP_I2C_CNT);
+       omap_i2c_dev->cmd_complete = 0;
+       omap_i2c_dev->cmd_err = 0;
+       w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+       if (msg->flags & I2C_M_TEN)
+               w |= OMAP_I2C_CON_XA;
+       if (!(msg->flags & I2C_M_RD))
+               w |= OMAP_I2C_CON_TRX;
+       if (stop)
+               w |= OMAP_I2C_CON_STP;
+       omap_i2c_write(omap_i2c_dev, w, OMAP_I2C_CON);
+
+       r = wait_event_interruptible_timeout(omap_i2c_dev->cmd_wait,
+                                            omap_i2c_dev->cmd_complete,
+                                            OMAP_I2C_TIMEOUT);
+
+       omap_i2c_dev->buf_len = 0;
+       if (r < 0)
+               return r;
+       if (!omap_i2c_dev->cmd_complete) {
+               omap_i2c_reset(omap_i2c_dev);
+               return -ETIMEDOUT;
+       }
+       if (!omap_i2c_dev->cmd_err)
+               return msg->len;
+
+       /* We have an error */
+       if (omap_i2c_dev->cmd_err & OMAP_I2C_STAT_NACK) {
+               if (msg->flags & I2C_M_IGNORE_NAK)
+                       return msg->len;
+               if (stop)
+                       omap_i2c_write(omap_i2c_dev,
+                               omap_i2c_read(omap_i2c_dev, OMAP_I2C_CON) |
+                                               OMAP_I2C_CON_STP,
+                               OMAP_I2C_CON);
+               return -EREMOTEIO;
+       }
+       if ((OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR | OMAP_I2C_STAT_XUDF)
+                       & omap_i2c_dev->cmd_err) {
+               omap_i2c_reset(omap_i2c_dev);
+               return -EIO;
+       }
+       return msg->len;
+}
+
+/*
+ * Prepare controller for a transaction and call omap_i2c_xfer_msg
+ * to do the work during IRQ processing.
+ */
+static int
+omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+       struct omap_i2c_dev *omap_i2c_dev = i2c_get_adapdata(adap);
+       int i;
+       int r = 0;
+
+       DEB1("msgs: %d\n", num);
+
+       if (num < 1 || num > MAX_MESSAGES)
+               return -EINVAL;
+
+       /* Check for valid parameters in messages */
+       for (i = 0; i < num; i++)
+               if (msgs[i].buf == NULL)
+                       return -EINVAL;
+
+// REVISIT: initialize and use adap->retries
+
+       if ((r = omap_i2c_wait_for_bb(omap_i2c_dev, 1)) < 0)
+               return r;
+
+       for (i = 0; i < num; i++) {
+               DEB2("msg: %d, addr: 0x%04x, len: %d, flags: 0x%x\n",
+                    i, msgs[i].addr, msgs[i].len, msgs[i].flags);
+
+               r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+
+               DEB2("r: %d\n", r);
+
+               if (r != msgs[i].len)
+                       break;
+       }
+
+       if (r >= 0 && num > 1)
+               r = num;
+
+       DEB2("r: %d\n", r);
+
+       return r;
+}
+
+static u32
+omap_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static inline void
+omap_i2c_complete_cmd(struct omap_i2c_dev *dev)
+{
+       dev->cmd_complete = 1;
+       wake_up(&dev->cmd_wait);
+}
+
+static irqreturn_t
+omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+       struct omap_i2c_dev *omap_i2c_dev = dev_id;
+       u16 bits;
+       u16 stat, w;
+       int count = 0;
+       u16 iv_read;
+
+       bits = omap_i2c_read(omap_i2c_dev, OMAP_I2C_IE);
+       while ((stat = omap_i2c_read(omap_i2c_dev, OMAP_I2C_STAT)) & bits) {
+
+               if (count++ == 100) {
+                       printk(KERN_WARNING "Too much work in one IRQ\n");
+                       break;
+               }
+
+               omap_i2c_write(omap_i2c_dev, stat, OMAP_I2C_STAT);
+               if (stat & OMAP_I2C_STAT_ARDY) {
+                       omap_i2c_complete_cmd(omap_i2c_dev);
+                       omap_i2c_write(omap_i2c_dev, OMAP_I2C_STAT_ARDY,
+                                      OMAP_I2C_STAT);
+                       if (omap_i2c_dev->rev1)
+                               iv_read = omap_i2c_read(omap_i2c_dev,
+                                                       OMAP_I2C_IV);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_RRDY) {
+                       w = omap_i2c_read(omap_i2c_dev, OMAP_I2C_DATA);
+                       if (omap_i2c_dev->buf_len) {
+                               *omap_i2c_dev->buf++ = w;
+                               omap_i2c_dev->buf_len--;
+                               if (omap_i2c_dev->buf_len) {
+                                       *omap_i2c_dev->buf++ = w >> 8;
+                                       omap_i2c_dev->buf_len--;
+                               }
+                               if (omap_i2c_dev->rev1 &&
+                                   !omap_i2c_dev->buf_len)
+                                       omap_i2c_complete_cmd(omap_i2c_dev);
+                       } else
+                               pr_err("RRDY IRQ while no data requested");
+                       omap_i2c_write(omap_i2c_dev, OMAP_I2C_STAT_RRDY,
+                                       OMAP_I2C_STAT);
+                       if (omap_i2c_dev->rev1)
+                               iv_read = omap_i2c_read(omap_i2c_dev,
+                                                       OMAP_I2C_IV);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_XRDY) {
+                       w = 0;
+                       if (omap_i2c_dev->buf_len) {
+                               w = *omap_i2c_dev->buf++;
+                               omap_i2c_dev->buf_len--;
+                               if (omap_i2c_dev->buf_len) {
+                                       w |= *omap_i2c_dev->buf++ << 8;
+                                       omap_i2c_dev->buf_len--;
+                               }
+                       } else {
+                               pr_err("XRDY IRQ while no data to send");
+                               /* FIXME: shouldn't we bail out here? */
+                       }
+                       omap_i2c_write(omap_i2c_dev, w, OMAP_I2C_DATA);
+                       /* We have to make sure the XRDY bit is reset */
+                       omap_i2c_write(omap_i2c_dev, OMAP_I2C_STAT_XRDY,
+                                       OMAP_I2C_STAT);
+                       if (omap_i2c_dev->rev1) {
+                               iv_read = omap_i2c_read(omap_i2c_dev,
+                                                       OMAP_I2C_IV);
+                               if (!omap_i2c_dev->buf_len)
+                                       omap_i2c_complete_cmd(omap_i2c_dev);
+                       }
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_ROVR) {
+                       pr_err("Receive overrun\n");
+                       omap_i2c_dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+               }
+               if (stat & OMAP_I2C_STAT_XUDF) {
+                       pr_err("Transmit overflow\n");
+                       omap_i2c_dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+               }
+               if (stat & OMAP_I2C_STAT_NACK) {
+                       omap_i2c_dev->cmd_err |= OMAP_I2C_STAT_NACK;
+                       omap_i2c_complete_cmd(omap_i2c_dev);
+                       omap_i2c_write(omap_i2c_dev, OMAP_I2C_CON_STP,
+                                      OMAP_I2C_CON);
+               }
+               if (stat & OMAP_I2C_STAT_AL) {
+                       pr_err("Arbitration lost\n");
+                       omap_i2c_dev->cmd_err |= OMAP_I2C_STAT_AL;
+                       omap_i2c_complete_cmd(omap_i2c_dev);
+               }
+               if (omap_i2c_dev->rev1)
+                       iv_read = omap_i2c_read(omap_i2c_dev, OMAP_I2C_IV);
+
+       }
+       return IRQ_HANDLED;
+}
+
+static struct i2c_algorithm omap_i2c_algo = {
+       .master_xfer    = omap_i2c_xfer,
+       .functionality  = omap_i2c_func,
+};
+
+#ifdef CONFIG_ARCH_OMAP24XX
+static int omap_i2c_24xx_get_clocks(struct omap_i2c_dev *omap_i2c_dev, int bus)
+{
+       if (!cpu_is_omap24xx())
+               return 0;
+
+       omap_i2c_dev->iclk = clk_get(NULL,
+               bus == 1 ? "i2c1_ick" : "i2c2_ick");
+       if (IS_ERR(omap_i2c_dev->iclk)) {
+               return -ENODEV;
+       }
+
+       omap_i2c_dev->fclk = clk_get(NULL,
+               bus == 1 ? "i2c1_fck" : "i2c2_fck");
+       if (IS_ERR(omap_i2c_dev->fclk)) {
+               clk_put(omap_i2c_dev->fclk);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void omap_i2c_24xx_put_clocks(struct omap_i2c_dev *omap_i2c_dev)
+{
+       if (cpu_is_omap24xx()) {
+               clk_put(omap_i2c_dev->fclk);
+               clk_put(omap_i2c_dev->iclk);
+       }
+}
+
+static void omap_i2c_24xx_enable_clocks(struct omap_i2c_dev *omap_i2c_dev,
+                                       int enable)
+{
+       if (cpu_is_omap24xx()) {
+               if (enable) {
+                       clk_use(omap_i2c_dev->iclk);
+                       clk_use(omap_i2c_dev->fclk);
+               } else {
+                       clk_unuse(omap_i2c_dev->iclk);
+                       clk_unuse(omap_i2c_dev->fclk);
+               }
+       }
+}
+
+#else
+#define omap_i2c_24xx_get_clocks(x, y)         0
+#define omap_i2c_24xx_enable_clocks(x, y)      do {} while (0)
+#define omap_i2c_24xx_put_clocks(x)            do {} while (0)
+#endif
+
+static int
+omap_i2c_probe(struct device *dev)
+{
+       struct platform_device  *pdev = to_platform_device(dev);
+       struct omap_i2c_dev     *omap_i2c_dev;
+       struct i2c_adapter      *adap;
+       struct resource         *mem, *irq;
+       int r;
+
+       /* NOTE: driver uses the static register mapping */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               pr_err("%s: no mem resource?\n", driver_name);
+               return -ENODEV;
+       }
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq) {
+               pr_err("%s: no irq resource?\n", driver_name);
+               return -ENODEV;
+       }
+
+       r = (int) request_mem_region(mem->start, (mem->end - mem->start) + 1,
+                       driver_name);
+       if (!r) {
+               pr_err("%s: I2C region already claimed\n", driver_name);
+               return -EBUSY;
+       }
+
+       if (clock > 200)
+               clock = 400;    /* Fast mode */
+       else
+               clock = 100;    /* Standard mode */
+
+       if (own < 1 || own > 0x7f)
+               own = DEFAULT_OWN;
+
+       omap_i2c_dev = kmalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
+       if (!omap_i2c_dev) {
+               r = -ENOMEM;
+               goto do_release_region;
+       }
+       memset(omap_i2c_dev, 0, sizeof(struct omap_i2c_dev));
+
+       omap_i2c_dev->dev = dev;
+       omap_i2c_dev->irq = irq->start;
+       omap_i2c_dev->base = (void __iomem *)IO_ADDRESS(mem->start);
+       dev_set_drvdata(omap_i2c_dev->dev, omap_i2c_dev);
+       init_waitqueue_head(&omap_i2c_dev->cmd_wait);
+
+       if ((r = omap_i2c_24xx_get_clocks(omap_i2c_dev, pdev->id)) != 0)
+               goto do_free_mem;
+
+       omap_i2c_24xx_enable_clocks(omap_i2c_dev, 1);
+
+#ifdef CONFIG_ARCH_OMAP15XX
+       omap_i2c_dev->rev1 = omap_i2c_read(omap_i2c_dev, OMAP_I2C_REV) < 0x20;
+#endif
+
+       /* reset ASAP, clearing any IRQs */
+       omap_i2c_reset(omap_i2c_dev);
+
+       r = request_irq(omap_i2c_dev->irq, omap_i2c_isr, 0,
+                       driver_name, omap_i2c_dev);
+       if (r) {
+               pr_err("%s: failure requesting irq %i\n",
+                        driver_name, omap_i2c_dev->irq);
+               goto do_unuse_clocks;
+       }
+       r = omap_i2c_read(omap_i2c_dev, OMAP_I2C_REV) & 0xff;
+       pr_info("%s: bus %d rev%d.%d at %d KHz\n", driver_name,
+                       pdev->id - 1, r >> 4, r & 0xf, clock);
+
+       adap = &omap_i2c_dev->adapter;
+       i2c_set_adapdata(adap, omap_i2c_dev);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_HWMON;
+       strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+       adap->algo = &omap_i2c_algo;
+       adap->dev.parent = dev;
+       /* i2c device drivers may be active on return from add_adapter() */
+       r = i2c_add_adapter(adap);
+       if (r) {
+               pr_err("%s: failure adding adapter\n", driver_name);
+               goto do_free_irq;
+       }
+
+       return 0;
+
+do_free_irq:
+       free_irq(omap_i2c_dev->irq, omap_i2c_dev);
+do_unuse_clocks:
+       omap_i2c_24xx_enable_clocks(omap_i2c_dev, 0);
+       omap_i2c_24xx_put_clocks(omap_i2c_dev);
+do_free_mem:
+       kfree(omap_i2c_dev);
+do_release_region:
+       omap_i2c_write(omap_i2c_dev, 0, OMAP_I2C_CON);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+       return r;
+}
+
+static int
+omap_i2c_remove(struct device *dev)
+{
+       struct platform_device  *pdev = to_platform_device(dev);
+       struct omap_i2c_dev     *omap_i2c_dev = dev_get_drvdata(dev);
+       struct resource         *mem;
+
+       omap_i2c_write(omap_i2c_dev, 0, OMAP_I2C_CON);
+       i2c_del_adapter(&omap_i2c_dev->adapter);
+       free_irq(omap_i2c_dev->irq, omap_i2c_dev);
+       omap_i2c_24xx_enable_clocks(omap_i2c_dev, 0);
+       omap_i2c_24xx_put_clocks(omap_i2c_dev);
+       kfree(omap_i2c_dev);
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       return 0;
+}
+
+static struct device_driver omap_i2c_driver = {
+       .name           = (char *)driver_name,
+       .bus            = &platform_bus_type,
+       .probe          = omap_i2c_probe,
+       .remove         = omap_i2c_remove,
+};
+
+/* i2c may be needed to bring up other drivers */
+static int __init
+omap_i2c_init_driver(void)
+{
+       return driver_register(&omap_i2c_driver);
+}
+subsys_initcall(omap_i2c_init_driver);
+
+static void __exit omap_i2c_exit_driver(void)
+{
+       driver_unregister(&omap_i2c_driver);
+}
+module_exit(omap_i2c_exit_driver);
+
+MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
+MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-omap.h b/drivers/i2c/busses/i2c-omap.h
new file mode 100644 (file)
index 0000000..6716421
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  linux/drivers/i2c/i2c-omap1610.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      OMAP I2C register definitions
+ *
+ *  Copyright (C) 2004 Texas Instruments.
+ *
+ *  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.
+ * 
+ *  HISTORY:
+ * 
+ *  20040824: Thiago Radicchi <trr@dcc.ufmg.br>  DCC-UFMG / iNdT
+ *       Removed some ifdefs which broke compilation for some platforms.
+ *       Added new defintion for interrupt vector.
+ */
+
+/* I2C Registers: */
+
+#define OMAP_I2C_BASE        IO_ADDRESS(0xfffb3800)
+#define OMAP_I2C_IOSIZE      (0x40)
+#define OMAP_I2C_REV         (OMAP_I2C_BASE + 0x00)
+#define OMAP_I2C_IE          (OMAP_I2C_BASE + 0x04)
+#define OMAP_I2C_STAT        (OMAP_I2C_BASE + 0x08)
+#define OMAP_I2C_IV          (OMAP_I2C_BASE + 0x0c)
+#define OMAP_I2C_SYSS        (OMAP_I2C_BASE + 0x10)
+#define OMAP_I2C_BUF         (OMAP_I2C_BASE + 0x14)
+#define OMAP_I2C_CNT         (OMAP_I2C_BASE + 0x18)
+#define OMAP_I2C_DATA        (OMAP_I2C_BASE + 0x1c)
+#define OMAP_I2C_SYSC        (OMAP_I2C_BASE + 0x20)
+#define OMAP_I2C_CON         (OMAP_I2C_BASE + 0x24)
+#define OMAP_I2C_OA          (OMAP_I2C_BASE + 0x28)
+#define OMAP_I2C_SA          (OMAP_I2C_BASE + 0x2c)
+#define OMAP_I2C_PSC         (OMAP_I2C_BASE + 0x30)
+#define OMAP_I2C_SCLL        (OMAP_I2C_BASE + 0x34)
+#define OMAP_I2C_SCLH        (OMAP_I2C_BASE + 0x38)
+#define OMAP_I2C_SYSTEST     (OMAP_I2C_BASE + 0x3c)
+
+/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+
+#define OMAP_I2C_IE_XRDY_IE  (1 << 4)  /* Transmit data ready interrupt enable */
+#define OMAP_I2C_IE_RRDY_IE  (1 << 3)  /* Receive data ready interrupt enable */
+#define OMAP_I2C_IE_ARDY_IE  (1 << 2)  /* Register access ready interrupt enable */
+#define OMAP_I2C_IE_NACK_IE  (1 << 1)  /* No acknowledgment interrupt enable */
+#define OMAP_I2C_IE_AL_IE    (1 << 0)  /* Arbitration lost interrupt enable */
+
+/* I2C Status Register (OMAP_I2C_STAT): */
+
+#define OMAP_I2C_STAT_SBD    (1 << 15) /* Single byte data */
+#define OMAP_I2C_STAT_BB     (1 << 12) /* Bus busy */
+#define OMAP_I2C_STAT_ROVR   (1 << 11) /* Receive overrun */
+#define OMAP_I2C_STAT_XUDF   (1 << 10) /* Transmit underflow */
+#define OMAP_I2C_STAT_AAS    (1 << 9)  /* Address as slave */
+#define OMAP_I2C_STAT_AD0    (1 << 8)  /* Address zero */
+#define OMAP_I2C_STAT_XRDY   (1 << 4)  /* Transmit data ready */
+#define OMAP_I2C_STAT_RRDY   (1 << 3)  /* Receive data ready */
+#define OMAP_I2C_STAT_ARDY   (1 << 2)  /* Register access ready */
+#define OMAP_I2C_STAT_NACK   (1 << 1)  /* No acknowledgment interrupt enable */
+#define OMAP_I2C_STAT_AL     (1 << 0)  /* Arbitration lost interrupt enable */
+
+/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
+
+#define OMAP_I2C_BUF_RDMA_EN         (1 << 15) /* Receive DMA channel enable */
+#define OMAP_I2C_BUF_XDMA_EN         (1 << 7)  /* Transmit DMA channel enable */
+
+/* I2C Configuration Register (OMAP_I2C_CON): */
+
+#define OMAP_I2C_CON_EN      (1 << 15) /* I2C module enable */
+#define OMAP_I2C_CON_RST     (0 << 15)  /* I2C module reset */
+#define OMAP_I2C_CON_BE      (1 << 14) /* Big endian mode */
+#define OMAP_I2C_CON_STB     (1 << 11) /* Start byte mode (master mode only) */
+#define OMAP_I2C_CON_MST     (1 << 10) /* Master/slave mode */
+#define OMAP_I2C_CON_TRX     (1 << 9)  /* Transmitter/receiver mode (master mode only) */
+#define OMAP_I2C_CON_XA      (1 << 8)  /* Expand address */
+#define OMAP_I2C_CON_RM      (1 << 2)  /* Repeat mode (master mode only) */
+#define OMAP_I2C_CON_STP     (1 << 1)  /* Stop condition (master mode only) */
+#define OMAP_I2C_CON_STT     (1 << 0)  /* Start condition (master mode only) */
+
+/* I2C System Test Register (OMAP_I2C_SYSTEST): */
+
+#define OMAP_I2C_SYSTEST_ST_EN       (1 << 15) /* System test enable */
+#define OMAP_I2C_SYSTEST_FREE        (1 << 14) /* Free running mode (on breakpoint) */
+#define OMAP_I2C_SYSTEST_TMODE_MASK  (3 << 12) /* Test mode select */
+#define OMAP_I2C_SYSTEST_TMODE_SHIFT (12)      /* Test mode select */
+#define OMAP_I2C_SYSTEST_SCL_I       (1 << 3)  /* SCL line sense input value */
+#define OMAP_I2C_SYSTEST_SCL_O       (1 << 2)  /* SCL line drive output value */
+#define OMAP_I2C_SYSTEST_SDA_I       (1 << 1)  /* SDA line sense input value */
+#define OMAP_I2C_SYSTEST_SDA_O       (1 << 0)  /* SDA line drive output value */
+
+/* I2C System Status register (OMAP_I2C_SYSS): */
+
+#define OMAP_I2C_SYSS_RDONE          1 /* Reset Done */
+
+/* I2C System Configuration Register (OMAP_I2C_SYSC): */
+
+#define OMAP_I2C_SYSC_SRST           (1 << 1)  /* Soft Reset */
index f9fae28f5612d8406820f38179e0bcfdf631d399..892321f721026453f07ed9b0705a2e6dd8747948 100644 (file)
@@ -102,6 +102,26 @@ config TPS65010
          This driver can also be built as a module.  If so, the module
          will be called tps65010.
 
+config SENSORS_TLV320AIC23
+       tristate "Texas Instruments TLV320AIC23 Codec"
+       depends on I2C && I2C_OMAP
+       help
+         If you say yes here you get support for the I2C control
+         interface for Texas Instruments TLV320AIC23 audio codec.
+
+config GPIOEXPANDER_OMAP
+       bool "GPIO Expander PCF8574PWR for OMAP"
+       depends on I2C && ARCH_OMAP16XX
+       help
+         If you say yes here you get support for I/O expander calls
+         to configure IrDA, Camera and audio devices endmenu
+
+config MENELAUS
+       bool "Menelaus PM chip"
+       depends on I2C=y && ARCH_OMAP24XX
+       help
+         Say yes here if you have Menelaus chip on your board
+
 config SENSORS_M41T00
        tristate "ST M41T00 RTC chip"
        depends on I2C && PPC32
index 46178b57b1f1e110a22cf6e5ba8c48f63e098a6a..316b67d9a735bdefee8f1d14d7b943216985d973 100644 (file)
@@ -13,6 +13,9 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
 obj-$(CONFIG_SENSORS_RTC8564)  += rtc8564.o
 obj-$(CONFIG_ISP1301_OMAP)     += isp1301_omap.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
+obj-$(CONFIG_SENSORS_TLV320AIC23) += tlv320aic23.o
+obj-$(CONFIG_GPIOEXPANDER_OMAP)        += gpio_expander_omap.o
+obj-$(CONFIG_MENELAUS)         += menelaus.o
 obj-$(CONFIG_RTC_X1205_I2C)    += x1205.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
diff --git a/drivers/i2c/chips/gpio_expander_omap.c b/drivers/i2c/chips/gpio_expander_omap.c
new file mode 100644 (file)
index 0000000..7f42864
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * drivers/i2c/chips/gpio_expander_omap.c
+ *
+ * Copyright (C) 2004 Texas Instruments Inc
+ * Author:
+ *
+ * gpio expander is used to configure IrDA, camera and audio devices on omap 1710 processor.
+ * 
+ * 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/types.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+
+int read_gpio_expa(u8 * val, int addr);
+int write_gpio_expa(u8 val, int addr);
+
+#define OMAP_IRDA_DEBUG        0       
+
+#if (OMAP_IRDA_DEBUG > 0)
+#define DBG(format, args...) printk(KERN_ERR "%s(): " format, __FUNCTION__, ## args);
+#define DBG_IRQ(format, args...) printk(KERN_ERR "%s(): " format, __FUNCTION__, ## args);
+#else
+#define DBG(format, args...)
+#define DBG_IRQ(format, args...)
+#endif
+
+int write_gpio_expa(u8 val, int addr)
+{
+       struct i2c_adapter *adap;
+       int err;
+       struct i2c_msg msg[1];
+       unsigned char data[1];
+
+       adap = i2c_get_adapter(0);
+       if (!adap)
+               return -ENODEV;
+       msg->addr = addr;       /* I2C address of GPIO EXPA */
+       msg->flags = 0;
+       msg->len = 1;
+       msg->buf = data;
+       data[0] = val;
+       err = i2c_transfer(adap, msg, 1);
+       if (err >= 0)
+               return 0;
+       return err;
+}
+
+/* Read from I/O EXPANDER on the H3 board.
+ * The IO expanders need an independent I2C client driver.
+ */
+
+int read_gpio_expa(u8 * val, int addr)
+{
+       struct i2c_adapter *adap;
+       int err;
+       struct i2c_msg msg[1];
+       unsigned char data[1];
+
+       adap = i2c_get_adapter(0);
+       if (!adap)
+               return -ENODEV;
+       msg->addr = addr;       /* I2C address of GPIO EXPA */
+       msg->flags = I2C_M_RD;
+       msg->len = 2;
+       msg->buf = data;
+       err = i2c_transfer(adap, msg, 1);
+       *val = data[0];
+
+       DBG("I2C: Read data is %x\n", (u8) * data);
+       if (err >= 0)
+               return 0;
+       return err;
+}
+
+EXPORT_SYMBOL(read_gpio_expa);
+EXPORT_SYMBOL(write_gpio_expa);
+
index 9dbb72fffbe2520fdcc47d220cb272adf4a81be4..14734431d935eea1a40cc33cfc3bbc6cbdca64f7 100644 (file)
 #include <linux/workqueue.h>
 
 #include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/mux.h>
 
 
 #ifndef        DEBUG
@@ -91,14 +95,11 @@ struct isp1301 {
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_MACH_OMAP_H2
+#if    defined(CONFIG_MACH_OMAP_H2) || \
+       defined(CONFIG_MACH_OMAP_H3)
 
 /* board-specific PM hooks */
 
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
-#include <asm/mach-types.h>
-
 
 #if    defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
 
@@ -129,17 +130,30 @@ static void enable_vbus_source(struct isp1301 *isp)
 }
 
 
-/* products will deliver OTG messages with LEDs, GUI, etc */
-static inline void notresponding(struct isp1301 *isp)
+#else
+
+static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
 {
-       printk(KERN_NOTICE "OTG device not responding.\n");
+       pr_debug("%s UNIMPL\n", __FUNCTION__);
 }
 
+static void enable_vbus_source(struct isp1301 *isp)
+{
+       pr_debug("%s UNIMPL\n", __FUNCTION__);
+}
 
 #endif
 
 /*-------------------------------------------------------------------------*/
 
+/* products will deliver OTG messages with LEDs, GUI, etc */
+static inline void notresponding(struct isp1301 *isp)
+{
+       printk(KERN_NOTICE "OTG device not responding.\n");
+}
+
+/*-------------------------------------------------------------------------*/
+
 /* only two addresses possible */
 #define        ISP_BASE                0x2c
 static unsigned short normal_i2c[] = {
@@ -515,6 +529,7 @@ static inline void check_state(struct isp1301 *isp, const char *tag) { }
 static void update_otg1(struct isp1301 *isp, u8 int_src)
 {
        u32     otg_ctrl;
+       u8      int_id;
 
        otg_ctrl = OTG_CTRL_REG
                        & OTG_CTRL_MASK
@@ -528,7 +543,10 @@ static void update_otg1(struct isp1301 *isp, u8 int_src)
        }
        if (int_src & INTR_VBUS_VLD)
                otg_ctrl |= OTG_VBUSVLD;
-       if (int_src & INTR_ID_GND) {            /* default-A */
+
+       int_id = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
+
+       if (int_id & INTR_ID_GND) {             /* default-A */
                if (isp->otg.state == OTG_STATE_B_IDLE
                                || isp->otg.state == OTG_STATE_UNDEFINED) {
                        a_idle(isp, "init");
@@ -1082,7 +1100,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
        /* update the OTG controller state to match the isp1301; may
         * trigger OPRT_CHG irqs for changes going to the isp1301.
         */
-       update_otg1(isp, isp_stat);
+       update_otg1(isp, stat); // pass the actual interrupt latch status
        update_otg2(isp, isp_bstat);
        check_state(isp, __FUNCTION__);
 #endif
@@ -1223,6 +1241,9 @@ static int isp1301_detach_client(struct i2c_client *i2c)
        if (machine_is_omap_h2())
                omap_free_gpio(2);
 
+       if (machine_is_omap_h3())
+               omap_free_gpio(14);
+
        isp->timer.data = 0;
        set_bit(WORK_STOP, &isp->todo);
        del_timer_sync(&isp->timer);
@@ -1301,7 +1322,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
 
        power_up(isp);
 
-       if (machine_is_omap_h2())
+       if (machine_is_omap_h2() || machine_is_omap_h3())
                isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
 
        dev_info(&isp->client.dev, "A-Host sessions ok\n");
@@ -1364,13 +1385,13 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
        power_up(isp);
        isp->otg.state = OTG_STATE_B_IDLE;
 
-       if (machine_is_omap_h2())
+       if (machine_is_omap_h2() || machine_is_omap_h3())
                isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
 
        isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
-               INTR_SESS_VLD);
+               INTR_SESS_VLD | INTR_VBUS_VLD);
        isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
-               INTR_VBUS_VLD);
+               INTR_VBUS_VLD | INTR_SESS_VLD);
        dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
        dump_regs(isp, __FUNCTION__);
 
@@ -1447,6 +1468,10 @@ isp1301_start_hnp(struct otg_transceiver *dev)
         * So do this part as early as possible...
         */
        switch (isp->otg.state) {
+       case OTG_STATE_B_PERIPHERAL:
+               isp->otg.state = OTG_STATE_B_WAIT_ACON;
+               isp1301_defer_work(isp, WORK_UPDATE_ISP);
+               break;
        case OTG_STATE_B_HOST:
                isp->otg.state = OTG_STATE_B_PERIPHERAL;
                /* caller will suspend next */
@@ -1562,19 +1587,30 @@ fail1:
        }
 #endif
 
-       if (machine_is_omap_h2()) {
+       if (machine_is_omap_h2() || machine_is_omap_h3()) {
                /* full speed signaling by default */
                isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
                        MC1_SPEED_REG);
                isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
                        MC2_SPD_SUSP_CTRL);
+       }
 
+       if (machine_is_omap_h2()) {
                /* IRQ wired at M14 */
                omap_cfg_reg(M14_1510_GPIO2);
                isp->irq = OMAP_GPIO_IRQ(2);
                omap_request_gpio(2);
                omap_set_gpio_direction(2, 1);
-               omap_set_gpio_edge_ctrl(2, OMAP_GPIO_FALLING_EDGE);
+               set_irq_type(isp->irq, IRQT_FALLING);
+       }
+
+       if (machine_is_omap_h3()) {
+               /* IRQ wired at N21 */
+               omap_cfg_reg(N21_1710_GPIO14);
+               isp->irq = OMAP_GPIO_IRQ(14);
+               omap_request_gpio(14);
+               omap_set_gpio_direction(14, 1);
+               set_irq_type(isp->irq, IRQT_FALLING);
        }
 
        status = request_irq(isp->irq, isp1301_irq,
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c
new file mode 100644 (file)
index 0000000..f77c9df
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * drivers/i2c/chips/menelaus.c
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Some parts based tps65010.c:
+ * Copyright (C) 2004 Texas Instruments and
+ * Copyright (C) 2004-2005 David Brownell
+ *
+ * Some parts based on tlv320aic24.c:
+ * Copyright (C) by Kai Svahn <kai.svahn@nokia.com>
+ *
+ * Changes for interrupt handling and clean-up by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * 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/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/menelaus.h>
+
+#define DRIVER_NAME                    "menelaus"
+
+#define pr_err(fmt, arg...)    printk(KERN_ERR DRIVER_NAME ": ", ## arg);
+
+#define MENELAUS_I2C_ADDRESS           0x72
+
+#define MENELAUS_REV                   0x01
+#define MENELAUS_VCORE_CTRL1           0x02
+#define MENELAUS_VCORE_CTRL2           0x03
+#define MENELAUS_VCORE_CTRL3           0x04
+#define MENELAUS_VCORE_CTRL4           0x05
+#define MENELAUS_VCORE_CTRL5           0x06
+#define MENELAUS_DCDC_CTRL1            0x07
+#define MENELAUS_DCDC_CTRL2            0x08
+#define MENELAUS_DCDC_CTRL3            0x09
+#define MENELAUS_LDO_CTRL1             0x0A
+#define MENELAUS_LDO_CTRL2             0x0B
+#define MENELAUS_LDO_CTRL3             0x0C
+#define MENELAUS_LDO_CTRL4             0x0D
+#define MENELAUS_LDO_CTRL5             0x0E
+#define MENELAUS_LDO_CTRL6             0x0F
+#define MENELAUS_LDO_CTRL7             0x10
+#define MENELAUS_LDO_CTRL8             0x11
+#define MENELAUS_SLEEP_CTRL1           0x12
+#define MENELAUS_SLEEP_CTRL2           0x13
+#define MENELAUS_DEVICE_OFF            0x14
+#define MENELAUS_OSC_CTRL              0x15
+#define MENELAUS_DETECT_CTRL           0x16
+#define MENELAUS_INT_MASK1             0x17
+#define MENELAUS_INT_MASK2             0x18
+#define MENELAUS_INT_STATUS1           0x19
+#define MENELAUS_INT_STATUS2           0x1A
+#define MENELAUS_INT_ACK1              0x1B
+#define MENELAUS_INT_ACK2              0x1C
+#define MENELAUS_GPIO_CTRL             0x1D
+#define MENELAUS_GPIO_IN               0x1E
+#define MENELAUS_GPIO_OUT              0x1F
+#define MENELAUS_BBSMS                 0x20
+#define MENELAUS_RTC_CTRL              0x21
+#define MENELAUS_RTC_UPDATE            0x22
+#define MENELAUS_RTC_SEC               0x23
+#define MENELAUS_RTC_MIN               0x24
+#define MENELAUS_RTC_HR                        0x25
+#define MENELAUS_RTC_DAY               0x26
+#define MENELAUS_RTC_MON               0x27
+#define MENELAUS_RTC_YR                        0x28
+#define MENELAUS_RTC_WKDAY             0x29
+#define MENELAUS_RTC_AL_SEC            0x2A
+#define MENELAUS_RTC_AL_MIN            0x2B
+#define MENELAUS_RTC_AL_HR             0x2C
+#define MENELAUS_RTC_AL_DAY            0x2D
+#define MENELAUS_RTC_AL_MON            0x2E
+#define MENELAUS_RTC_AL_YR             0x2F
+#define MENELAUS_RTC_COMP_MSB          0x30
+#define MENELAUS_RTC_COMP_LSB          0x31
+#define MENELAUS_S1_PULL_EN            0x32
+#define MENELAUS_S1_PULL_DIR           0x33
+#define MENELAUS_S2_PULL_EN            0x34
+#define MENELAUS_S2_PULL_DIR           0x35
+#define MENELAUS_MCT_CTRL1             0x36
+#define MENELAUS_MCT_CTRL2             0x37
+#define MENELAUS_MCT_CTRL3             0x38
+#define MENELAUS_MCT_PIN_ST            0x39
+#define MENELAUS_DEBOUNCE1             0x3A
+
+#define IH_MENELAUS_IRQS               12
+#define MENELAUS_MMC_S1CD_IRQ          0       /* MMC slot 1 card change */
+#define MENELAUS_MMC_S2CD_IRQ          1       /* MMC slot 2 card change */
+#define MENELAUS_MMC_S1D1_IRQ          2       /* MMC DAT1 low in slot 1 */
+#define MENELAUS_MMC_S2D1_IRQ          3       /* MMC DAT1 low in slot 2 */
+#define MENELAUS_LOWBAT_IRQ            4       /* Low battery */
+#define MENELAUS_HOTDIE_IRQ            5       /* Hot die detect */
+#define MENELAUS_UVLO_IRQ              6       /* UVLO detect */
+#define MENELAUS_TSHUT_IRQ             7       /* Thermal shutdown */
+#define MENELAUS_RTCTMR_IRQ            8       /* RTC timer */
+#define MENELAUS_RTCALM_IRQ            9       /* RTC alarm */
+#define MENELAUS_RTCERR_IRQ            10      /* RTC error */
+#define MENELAUS_PSHBTN_IRQ            11      /* Push button */
+#define MENELAUS_RESERVED12_IRQ                12      /* Reserved */
+#define MENELAUS_RESERVED13_IRQ                13      /* Reserved */
+#define MENELAUS_RESERVED14_IRQ                14      /* Reserved */
+#define MENELAUS_RESERVED15_IRQ                15      /* Reserved */
+
+static void menelaus_work(void * _menelaus);
+
+/* Initialized by menelaus_init */
+static unsigned short normal_i2c[] = { MENELAUS_I2C_ADDRESS, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+struct menelaus_chip {
+       unsigned long           initialized;
+       struct semaphore        lock;
+       struct i2c_client       client;
+       struct work_struct      work;
+       int                     irq;
+       void                    *handlers[16];
+       void                    (*mmc_callback)(unsigned long data, u8 mask);
+       unsigned long           mmc_callback_data;
+};
+
+static struct menelaus_chip menelaus;
+
+static void menelaus_write(u8 value, u8 reg)
+{
+       if (i2c_smbus_write_byte_data(&menelaus.client, reg, value) < 0)
+               pr_err("write error");
+}
+
+static u8 menelaus_read(u8 reg)
+{
+       int val = i2c_smbus_read_byte_data(&menelaus.client, reg);
+
+       if (val < 0) {
+               pr_err("read error");
+               return 0;
+       }
+
+       return val;
+}
+
+static void menelaus_enable_irq(int irq)
+{
+       if (irq > 7)
+               menelaus_write(menelaus_read(MENELAUS_INT_MASK2) &
+                              ~(1 << (irq - 8)), MENELAUS_INT_MASK2);
+       else
+               menelaus_write(menelaus_read(MENELAUS_INT_MASK1) &
+                              ~(1 << irq), MENELAUS_INT_MASK1);
+}
+
+static void menelaus_disable_irq(int irq)
+{
+       if (irq > 7)
+               menelaus_write(menelaus_read(MENELAUS_INT_MASK2)
+                              | (1 << (irq - 8)), MENELAUS_INT_MASK2);
+       else
+               menelaus_write(menelaus_read(MENELAUS_INT_MASK1)
+                              | (1 << irq), MENELAUS_INT_MASK1);
+}
+
+static void menelaus_ack_irq(int irq)
+{
+       if (irq > 7)
+               menelaus_write(1 << (irq - 8), MENELAUS_INT_ACK2);
+       else
+               menelaus_write(1 << irq, MENELAUS_INT_ACK1);    
+}
+
+/* Adds a handler for an interrupt. Does not run in interrupt context */
+static int menelaus_add_irq_work(int irq, void * handler)
+{
+       down(&menelaus.lock);
+       menelaus.handlers[irq] = handler;
+       menelaus_enable_irq(irq);
+       up(&menelaus.lock);
+
+       return 0;
+}
+
+/* Removes handler for an interrupt */
+static void menelaus_remove_irq_work(int irq)
+{
+       down(&menelaus.lock);
+       menelaus_disable_irq(irq);
+       menelaus.handlers[irq] = NULL;
+       up(&menelaus.lock);
+}
+
+/*-----------------------------------------------------------------------*/
+
+/*
+ * Toggles the MMC slots between open-drain and push-pull mode.
+ * We always set both slots the same way.
+ */
+void menelaus_mmc_opendrain(int enable)
+{
+       unsigned char reg = menelaus_read(MENELAUS_MCT_CTRL1);
+
+       if (enable)
+               reg |= (0x3 << 2);
+       else
+               reg &= ~(0x3 << 2);
+
+       menelaus_write(reg, MENELAUS_MCT_CTRL1);
+}
+EXPORT_SYMBOL(menelaus_mmc_opendrain);
+
+/*
+ * Gets scheduled when a card detect interrupt happens. Note that in some cases
+ * this line is wired to card cover switch rather than the card detect switch
+ * in each slot. In this case the cards are not seen by menelaus.
+ * FIXME: Add handling for D1 too
+ */
+static int menelaus_mmc_cd_work(struct menelaus_chip *menelaus)
+{
+       unsigned char reg;
+       unsigned char card_mask = 0;
+
+       reg = menelaus_read(MENELAUS_MCT_PIN_ST);
+
+       if (!(reg & 0x1))
+               card_mask |= (1 << 0);
+
+       if (!(reg & 0x2))
+               card_mask |= (1 << 1);
+
+       if (menelaus->mmc_callback)
+               menelaus->mmc_callback(menelaus->mmc_callback_data, card_mask);
+
+       return 0;
+}
+
+/* Initializes MMC slots */
+void menelaus_mmc_register(void (*callback)(u8 card_mask), unsigned long data)
+{
+       int reg;
+
+       /* DCDC3 to 3V */
+       reg = menelaus_read(MENELAUS_DCDC_CTRL1);
+       reg |= 0x6 << 4;
+       menelaus_write(reg, MENELAUS_DCDC_CTRL1);
+
+       reg = menelaus_read(MENELAUS_DCDC_CTRL3);
+       reg |= 0x6;
+       menelaus_write(reg, MENELAUS_DCDC_CTRL3);
+
+       /* Enable both slots, do not set auto shutdown */
+       reg = menelaus_read(MENELAUS_MCT_CTRL3);
+       reg |= 0x3;
+       menelaus_write(reg, MENELAUS_MCT_CTRL3);
+
+       /* Enable card detect for both slots, slot 2 powered from DCDC3 */
+       reg = menelaus_read(MENELAUS_MCT_CTRL2);
+       reg |= 0xf0;
+       menelaus_write(reg, MENELAUS_MCT_CTRL2);
+
+       /* Set both slots in open-drain mode, card detect normally closed */
+       reg = menelaus_read(MENELAUS_MCT_CTRL1);
+       reg |= 0xfc;
+       menelaus_write(reg, MENELAUS_MCT_CTRL1);
+
+       /* Set MMC voltage */
+       reg = menelaus_read(MENELAUS_LDO_CTRL7);
+       reg |= 0x03;
+       menelaus_write(reg, MENELAUS_LDO_CTRL7);
+
+       menelaus.mmc_callback_data = data;
+       menelaus.mmc_callback = callback;
+
+       menelaus_add_irq_work(MENELAUS_MMC_S1CD_IRQ, menelaus_mmc_cd_work);
+       menelaus_add_irq_work(MENELAUS_MMC_S2CD_IRQ, menelaus_mmc_cd_work);
+       menelaus_add_irq_work(MENELAUS_MMC_S1D1_IRQ, menelaus_mmc_cd_work);
+       menelaus_add_irq_work(MENELAUS_MMC_S2D1_IRQ, menelaus_mmc_cd_work);
+}
+EXPORT_SYMBOL(menelaus_mmc_register);
+
+void menelaus_mmc_remove(void)
+{
+       menelaus_remove_irq_work(MENELAUS_MMC_S1CD_IRQ);
+       menelaus_remove_irq_work(MENELAUS_MMC_S2CD_IRQ);
+       menelaus_remove_irq_work(MENELAUS_MMC_S1D1_IRQ);
+       menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ);
+
+       menelaus.mmc_callback = NULL;
+       menelaus.mmc_callback_data = 0;
+
+       /* FIXME: Shutdown MMC components of Menelaus */
+}
+EXPORT_SYMBOL(menelaus_mmc_remove);
+
+/*-----------------------------------------------------------------------*/
+
+/* Handles Menelaus interrupts. Does not run in interrupt context */
+static void menelaus_work(void * _menelaus)
+{
+       struct menelaus_chip *menelaus = _menelaus;
+       int (*handler)(struct menelaus_chip *menelaus);
+       while (1) {
+               int i;
+               unsigned char isr;
+
+               isr = menelaus_read(MENELAUS_INT_STATUS1) |
+                     (menelaus_read(MENELAUS_INT_STATUS2) << 8);
+
+               if (!isr)
+                       break;
+
+               for (i = 0; i < IH_MENELAUS_IRQS; i++) {
+                       if (isr & (1 << i)) {
+                               down(&menelaus->lock);
+                               menelaus_disable_irq(i);
+                               menelaus_ack_irq(i);
+                               if (menelaus->handlers[i]) {
+                                       handler = menelaus->handlers[i];
+                                       handler(menelaus);
+                               }
+                               menelaus_enable_irq(i);
+                               up(&menelaus->lock);
+                       }
+               }
+       }
+       enable_irq(menelaus->irq);
+}
+
+/*
+ * We cannot use I2C in interrupt context, so we just schedule work.
+ */
+static irqreturn_t menelaus_irq(int irq, void *_menelaus, struct pt_regs *regs)
+{
+       struct menelaus_chip *menelaus = _menelaus;
+
+       disable_irq_nosync(irq);
+       (void)schedule_work(&menelaus->work);
+
+       return IRQ_HANDLED;
+}
+
+static struct i2c_driver menelaus_i2c_driver;
+
+static int menelaus_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client       *c;
+       int                     rev = 0;
+       int                     err = 0, i;
+
+       if (test_and_set_bit(0, &menelaus.initialized))
+               return -EBUSY;
+
+       c = &menelaus.client;
+       strncpy(c->name, DRIVER_NAME, sizeof(c->name));
+       c->addr         = address;
+       c->adapter      = adapter;
+       c->driver       = &menelaus_i2c_driver;
+       c->flags        = 0;
+
+       if ((err = i2c_attach_client(c)) < 0) {
+               pr_err("couldn't attach\n");
+               goto fail1;
+       }
+
+       /* If a true probe check the device */
+       if (kind < 0 && (rev = menelaus_read(MENELAUS_REV)) < 0) {
+               pr_err("device not found");
+               err = -ENODEV;
+               goto fail2;
+       }
+
+       /* Most likely Menelaus interrupt is at SYS_NIRQ */
+       omap_cfg_reg(W19_24XX_SYS_NIRQ);
+       menelaus.irq = INT_24XX_SYS_NIRQ;
+
+       /* Disable all menelaus interrupts */
+       for (i = 0; i < 16; i++) {
+               menelaus_ack_irq(i);
+               menelaus_disable_irq(i);
+       }
+
+       err = request_irq(menelaus.irq, menelaus_irq, SA_INTERRUPT,
+                         DRIVER_NAME, &menelaus);
+       if (err)
+               printk(KERN_ERR "Could not get Menelaus IRQ\n");
+
+       init_MUTEX(&menelaus.lock);
+       INIT_WORK(&menelaus.work, menelaus_work, &menelaus);
+
+       if (kind < 0)
+               pr_info("Menelaus rev %d.%d\n", rev >> 4, rev & 0x0f);
+
+       return 0;
+
+fail2:
+       i2c_detach_client(c);
+fail1:
+       clear_bit(0, &menelaus.initialized);
+       return err;
+}
+
+static int menelaus_remove(struct i2c_client *client)
+{
+       int err;
+
+       free_irq(menelaus.irq, &menelaus);
+
+       if ((err = i2c_detach_client(client))) {
+               pr_err("client deregistration failed\n");
+               return err;
+       }
+
+       clear_bit(0, &menelaus.initialized);
+
+       return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+static int menelaus_scan_bus(struct i2c_adapter *bus)
+{
+       if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA |
+                                         I2C_FUNC_SMBUS_WRITE_BYTE)) {
+               pr_err("invalid i2c bus functionality\n");
+               return -EINVAL;
+       }
+
+       return i2c_probe(bus, &addr_data, menelaus_probe);
+}
+
+static struct i2c_driver menelaus_i2c_driver = {
+       .owner          = THIS_MODULE,
+       .name           = DRIVER_NAME,
+       .id             = I2C_DRIVERID_EXP0, /*FIXME:accroding to i2c-ids.h */
+       .class          = I2C_CLASS_HWMON,
+       .flags          = I2C_DF_NOTIFY,
+       .attach_adapter = menelaus_scan_bus,
+       .detach_client  = menelaus_remove,
+};
+
+static int __init menelaus_init(void)
+{
+       int res;
+
+       if ((res = i2c_add_driver(&menelaus_i2c_driver)) < 0) {
+               pr_err("driver registration failed\n");
+               return res;
+       }
+
+       return 0;
+}
+
+static void __exit menelaus_exit(void)
+{
+       if (i2c_del_driver(&menelaus_i2c_driver) < 0)
+               pr_err("driver remove failed\n");
+
+       /* FIXME: Shutdown menelaus parts that can be shut down */
+}
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("I2C interface for Menelaus.");
+MODULE_LICENSE("GPL");
+
+module_init(menelaus_init);
+module_exit(menelaus_exit);
diff --git a/drivers/i2c/chips/tlv320aic23.c b/drivers/i2c/chips/tlv320aic23.c
new file mode 100644 (file)
index 0000000..43c4bac
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *   Texas Instrumens TLV320AIC23 audio codec's i2c interface.
+ *   
+ *   Copyright (c) by Kai Svahn <kai.svahn@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 <linux/i2c.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/arch/aic23.h>
+
+#define TLV320AIC23_VERSION    "0.1"
+#define TLV320AIC23_DATE       "12-Aug-2004"
+
+/* I2C Addresses to scan */
+static unsigned short normal_i2c[] = { TLV320AIC23ID1, TLV320AIC23ID2, I2C_CLIENT_END };
+
+/* This makes all addr_data:s */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver tlv320aic23_driver; 
+static struct i2c_client *new_client;
+//static struct i2c_client *client;
+
+static int _tlv320aic23_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+       u8 val, wreg;
+       
+       /* TLV320AIC23 has 7 bit address and 9 bits of data
+        * so we need to switch one data bit into reg and rest
+        * of data into val
+        */
+       
+       wreg = (reg << 1);
+       val = (0x01 & (value >> 8));
+       wreg = (wreg | val);
+       val = (0x00ff & value);
+       
+       return i2c_smbus_write_byte_data(client, wreg, val);
+}
+
+int tlv320aic23_write_value(u8 reg, u16 value)
+{
+       static struct i2c_client *client;
+       client = new_client;
+       _tlv320aic23_write_value(client, reg, value);
+       
+       return 0;
+}
+
+static int tlv320aic23_detect_client(struct i2c_adapter *adapter, int address, 
+                                    int kind)
+{
+       int err = 0;
+       const char *client_name = "TLV320AIC23 Audio Codec";
+       
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA | 
+                                    I2C_FUNC_SMBUS_WRITE_BYTE)) {
+               printk(KERN_WARNING "%s functinality check failed\n", client_name);
+               return err;
+       }
+       
+       if (!(new_client = kmalloc(sizeof(struct i2c_client),
+                                  GFP_KERNEL))) {
+               err = -ENOMEM;
+               printk(KERN_WARNING "Couldn't allocate memory for %s\n", client_name);
+               return err;
+       }
+       
+       memset(new_client, 0x00, sizeof(struct i2c_client));
+       new_client->addr = address;
+       new_client->adapter = adapter;
+       new_client->driver = &tlv320aic23_driver;
+       new_client->flags = 0;
+       strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+               
+       if ((err = i2c_attach_client(new_client))) {
+               printk(KERN_WARNING "Couldn't attach %s\n", client_name);
+               kfree(new_client);
+               return err;
+       }
+       
+       return 0;
+}
+       
+static int tlv320aic23_detach_client(struct i2c_client *client)
+{
+       int err;
+       
+       if ((err = i2c_detach_client(client))) {
+               printk("tlv320aic23.o: Client deregistration failed, client not detached.\n");
+               return err;
+       }
+       
+       kfree(client);
+       return 0;
+}
+
+static int tlv320aic23_attach_adapter(struct i2c_adapter *adapter)
+{
+       int res;
+       
+       res = i2c_probe(adapter, &addr_data, &tlv320aic23_detect_client);
+       return res;
+}
+
+/*-----------------------------------------------------------------------*/
+
+static struct i2c_driver tlv320aic23_driver = {
+       .owner          = THIS_MODULE, 
+        .name           = "OMAP+TLV320AIC23 codec",
+        .id            = I2C_DRIVERID_EXP0,           /* Experimental ID */
+        .flags         = I2C_DF_NOTIFY,
+        .attach_adapter        = tlv320aic23_attach_adapter,
+        .detach_client = tlv320aic23_detach_client,
+};
+
+/*
+ *  INIT part
+ */
+
+static int __init tlv320aic23_init(void)
+{
+       int res;
+       struct i2c_client *client = client;
+       
+       if ((res = i2c_add_driver(&tlv320aic23_driver))) {
+               printk("tlv320aic23 i2c: Driver registration failed, module not inserted.\n");
+               return res;
+       }
+       
+       printk("TLV320AIC23 I2C version %s (%s)\n", TLV320AIC23_VERSION, 
+              TLV320AIC23_DATE);
+       
+       return 0;
+}
+
+static void __exit tlv320aic23_exit(void)
+{
+       int res;
+
+       if ((res = i2c_del_driver(&tlv320aic23_driver))) 
+               printk("tlv320aic23 i2c: Driver remove failed, module not removed.\n");
+}
+
+MODULE_AUTHOR("Kai Svahn <kai.svahn@nokia.com>");
+MODULE_DESCRIPTION("I2C interface for TLV320AIC23 codec.");
+MODULE_LICENSE("GPL");
+
+module_init(tlv320aic23_init)
+module_exit(tlv320aic23_exit)
+
+EXPORT_SYMBOL(tlv320aic23_write_value);
index 280dd7a45db65bee454d9db2bb49398b63678f52..f009caa9ef6a9193714fe47eceb8ff5674798018 100644 (file)
@@ -18,6 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#undef DEBUG
 
 #include <linux/config.h>
 #include <linux/kernel.h>
 MODULE_DESCRIPTION("TPS6501x Power Management Driver");
 MODULE_LICENSE("GPL");
 
-static unsigned short normal_i2c[] = { 0x48, /* 0x49, */ I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+/* only two addresses possible */
+#define        TPS_BASE        0x48
+static unsigned short normal_i2c[] = {
+       TPS_BASE,
+       I2C_CLIENT_END };
 
 I2C_CLIENT_INSMOD;
 
@@ -97,7 +101,7 @@ struct tps65010 {
        u8                      chgstatus, regstatus, chgconf;
        u8                      nmask1, nmask2;
 
-       /* not currently tracking GPIO state */
+       /* plus four GPIOs, probably used to switch power */
 };
 
 #define        POWER_POLL_DELAY        msecs_to_jiffies(800)
@@ -130,7 +134,7 @@ static void dbg_regstat(char *buf, size_t len, u8 regstatus)
                (regstatus & TPS_REG_COVER) ? " uncover" : "",
                (regstatus & TPS_REG_UVLO) ? " UVLO" : "",
                (regstatus & TPS_REG_NO_CHG) ? " NO_CHG" : "",
-               (regstatus & TPS_REG_PG_LD02) ? " ld02_bad" : "",
+               (regstatus & TPS_REG_PG_LD02) ? " ld01_bad" : "",
                (regstatus & TPS_REG_PG_LD01) ? " ld01_bad" : "",
                (regstatus & TPS_REG_PG_MAIN) ? " main_bad" : "",
                (regstatus & TPS_REG_PG_CORE) ? " core_bad" : "");
@@ -138,7 +142,7 @@ static void dbg_regstat(char *buf, size_t len, u8 regstatus)
 
 static void dbg_chgconf(int por, char *buf, size_t len, u8 chgconfig)
 {
-       const char *hibit;
+       char *hibit;
 
        if (por)
                hibit = (chgconfig & TPS_CHARGE_POR)
@@ -290,7 +294,7 @@ static int dbg_show(struct seq_file *s, void *_)
        seq_printf(s, "defgpio %02x mask3 %02x\n", value, v2);
 
        for (i = 0; i < 4; i++) {
-               if (value & (1 << (4 + i)))
+               if (value & (1 << (4 +i)))
                        seq_printf(s, "  gpio%d-out %s\n", i + 1,
                                (value & (1 << i)) ? "low" : "hi ");
                else
@@ -476,7 +480,7 @@ static int __exit tps65010_detach_client(struct i2c_client *client)
        debugfs_remove(tps->file);
        if (i2c_detach_client(client) == 0)
                kfree(tps);
-       the_tps = NULL;
+       the_tps = 0;
        return 0;
 }
 
@@ -508,6 +512,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
        INIT_WORK(&tps->work, tps65010_work, tps);
        tps->irq = -1;
        tps->client.addr = address;
+       i2c_set_clientdata(&tps->client, tps);
        tps->client.adapter = bus;
        tps->client.driver = &tps65010_driver;
        strlcpy(tps->client.name, DRIVER_NAME, I2C_NAME_SIZE);
@@ -516,7 +521,9 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
        if (status < 0) {
                dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
                                DRIVER_NAME, address, status);
-               goto fail1;
+fail1:
+               kfree(tps);
+               return 0;
        }
 
 #ifdef CONFIG_ARM
@@ -624,9 +631,6 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
        tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
                                tps, DEBUG_FOPS);
        return 0;
-fail1:
-       kfree(tps);
-       return 0;
 }
 
 static int __init tps65010_scan_bus(struct i2c_adapter *bus)
@@ -639,6 +643,7 @@ static int __init tps65010_scan_bus(struct i2c_adapter *bus)
 static struct i2c_driver tps65010_driver = {
        .owner          = THIS_MODULE,
        .name           = "tps65010",
+       .id             = 888,          /* FIXME assign "official" value */
        .flags          = I2C_DF_NOTIFY,
        .attach_adapter = tps65010_scan_bus,
        .detach_client  = __exit_p(tps65010_detach_client),
@@ -693,14 +698,14 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
                return -ENODEV;
        if ((gpio < GPIO1) || (gpio > GPIO4))
                return -EINVAL;
-
+       
        down(&the_tps->lock);
 
        defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO);
 
        /* Configure GPIO for output */
        defgpio |= 1 << (gpio + 3);
-
+       
        /* Writing 1 forces a logic 0 on that GPIO and vice versa */
        switch (value) {
        case LOW:
@@ -711,14 +716,14 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
                defgpio &= ~(1 << (gpio - 1)); /* set GPIO high by writing 0 */
                break;
        }
-
+       
        status = i2c_smbus_write_byte_data(&the_tps->client,
                TPS_DEFGPIO, defgpio);
 
        pr_debug("%s: gpio%dout = %s, defgpio 0x%02x\n", DRIVER_NAME,
                gpio, value ? "high" : "low",
                i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO));
-
+       
        up(&the_tps->lock);
        return status;
 }
@@ -737,7 +742,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
        if (!the_tps)
                return -ENODEV;
 
-       if (led == LED1)
+       if(led == LED1)
                offs = 0;
        else {
                offs = 2;
@@ -746,14 +751,12 @@ int tps65010_set_led(unsigned led, unsigned mode)
 
        down(&the_tps->lock);
 
-       pr_debug("%s: led%i_on   0x%02x\n", DRIVER_NAME, led,
-               i2c_smbus_read_byte_data(&the_tps->client,
-                               TPS_LED1_ON + offs));
-
-       pr_debug("%s: led%i_per  0x%02x\n", DRIVER_NAME, led,
-               i2c_smbus_read_byte_data(&the_tps->client,
-                               TPS_LED1_PER + offs));
+       dev_dbg (&the_tps->client.dev, "led%i_on   0x%02x\n", led,
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
 
+       dev_dbg (&the_tps->client.dev, "led%i_per  0x%02x\n", led,
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
+       
        switch (mode) {
        case OFF:
                led_on  = 1 << 7;
@@ -768,7 +771,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
                led_per = 0x08 | (1 << 7);
                break;
        default:
-               printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n",
+               printk(KERN_ERR "%s: Wrong mode parameter for tps65010_set_led()\n", 
                       DRIVER_NAME);
                up(&the_tps->lock);
                return -EINVAL;
@@ -778,28 +781,27 @@ int tps65010_set_led(unsigned led, unsigned mode)
                        TPS_LED1_ON + offs, led_on);
 
        if (status != 0) {
-               printk(KERN_ERR "%s: Failed to write led%i_on register\n",
+               printk(KERN_ERR "%s: Failed to write led%i_on register\n", 
                       DRIVER_NAME, led);
                up(&the_tps->lock);
                return status;
-       }
+       } 
 
-       pr_debug("%s: led%i_on   0x%02x\n", DRIVER_NAME, led,
+       dev_dbg (&the_tps->client.dev, "led%i_on   0x%02x\n", led,
                i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
 
        status = i2c_smbus_write_byte_data(&the_tps->client,
                        TPS_LED1_PER + offs, led_per);
 
        if (status != 0) {
-               printk(KERN_ERR "%s: Failed to write led%i_per register\n",
+               printk(KERN_ERR "%s: Failed to write led%i_per register\n", 
                       DRIVER_NAME, led);
                up(&the_tps->lock);
                return status;
        }
 
-       pr_debug("%s: led%i_per  0x%02x\n", DRIVER_NAME, led,
-               i2c_smbus_read_byte_data(&the_tps->client,
-                               TPS_LED1_PER + offs));
+       dev_dbg (&the_tps->client.dev, "led%i_per  0x%02x\n", led,
+               i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
 
        up(&the_tps->lock);
 
@@ -854,7 +856,7 @@ int tps65010_set_low_pwr(unsigned mode)
                i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
 
        vdcdc1 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1);
-
+       
        switch (mode) {
        case OFF:
                vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
@@ -869,8 +871,8 @@ int tps65010_set_low_pwr(unsigned mode)
                        TPS_VDCDC1, vdcdc1);
 
        if (status != 0)
-               printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
-                       DRIVER_NAME);
+               printk(KERN_ERR "%s: Failed to write vdcdc1 register\n", 
+                      DRIVER_NAME);
        else
                pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
                        i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
@@ -895,15 +897,15 @@ int tps65010_config_vregs1(unsigned value)
 
        down(&the_tps->lock);
 
-       pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
-                       i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
+       pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, 
+                       i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
 
        status = i2c_smbus_write_byte_data(&the_tps->client,
                        TPS_VREGS1, value);
 
        if (status != 0)
-               printk(KERN_ERR "%s: Failed to write vregs1 register\n",
-                       DRIVER_NAME);
+               printk(KERN_ERR "%s: Failed to write vregs1 register\n", 
+                       DRIVER_NAME);
        else
                pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
                        i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
@@ -1005,7 +1007,7 @@ static int __init tps_init(void)
                msleep(10);
        }
 
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARM)
        if (machine_is_omap_osk()) {
 
                // FIXME: More should be placed in the initialization code
@@ -1045,8 +1047,8 @@ static int __init tps_init(void)
        } else if (machine_is_omap_h3()) {
                /* gpio4 for SD, gpio3 for VDD_DSP */
 #ifdef CONFIG_PM
-               /* Enable LOW_PWR */
-               tps65013_set_low_pwr(ON);
+               /* FIXME: Enable LOW_PWR hangs H3 */
+               //tps65013_set_low_pwr(ON);
 #endif
        }
 #endif
index 4a917748fd9ffac79f863675574ffd2155994858..a52757c4581713a6322149f8b2b5adbfe12936d0 100644 (file)
@@ -193,4 +193,24 @@ config KEYBOARD_HIL
          This driver implements support for HIL-keyboards attached
          to your machine, so normally you should say Y here.
 
+
+config KEYBOARD_OMAP
+       tristate "TI OMAP keypad support"
+       depends on ARCH_OMAP1
+       help
+         Say Y here if you want to use the OMAP keypad.
+
+         To compile this driver as a module, choose M here: the
+         module will be called omap-keypad.
+
+config OMAP_PS2
+       tristate "TI OMAP Innovator 1510 PS/2 keyboard & mouse support"
+       depends on ARCH_OMAP15XX && MACH_OMAP_INNOVATOR
+       help
+         Say Y here if you want to use the OMAP Innovator 1510 PS/2
+         keyboard and mouse.
+
+         To compile this driver as a module, choose M here: the
+         module will be called innovator_ps2.
+         
 endif
index 9ce0b87f2facb9fc06fde3ffd497d52b88c0b72c..df33964341f0d51cb55cfb0a2ecc241349d55c0d 100644 (file)
@@ -17,4 +17,5 @@ obj-$(CONFIG_KEYBOARD_CORGI)          += corgikbd.o
 obj-$(CONFIG_KEYBOARD_SPITZ)           += spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
-
+obj-$(CONFIG_KEYBOARD_OMAP)             += omap-keypad.o
+obj-$(CONFIG_OMAP_PS2)                 += innovator_ps2.o
diff --git a/drivers/input/keyboard/innovator_ps2.c b/drivers/input/keyboard/innovator_ps2.c
new file mode 100644 (file)
index 0000000..c0889dc
--- /dev/null
@@ -0,0 +1,1291 @@
+/*
+ * drivers/char/innovator_ps2.c
+ *
+ * Basic PS/2 keyboard/mouse driver for the Juno® USAR HID controller
+ * present on the TI Innovator/OMAP1510 Break-out-board.
+ *
+ *
+ * Author: MontaVista Software, Inc.
+ *         <gdavis@mvista.com> or <source@mvista.com>
+ *
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ *
+ * REFERENCES:
+ *
+ * 1.  Technical Reference Manual
+ *     Juno® 01
+ *     Multi-function ICs family
+ *     UR8HC007-001 HID & Power management controller
+ *     Document Number: DOC8-007-001-TR-075
+ *     Date: February 2002
+ *     Copyright Â©1998-2002 Semtech Corporation
+ *     http://www.semtech.com/pdf/doc8-007-001-tr.pdf
+ *
+ * 2.  Juno® 01 UR8HC007-001 Data Sheet
+ *     Extremely Low-power Input Device and Power Management IC
+ *     Copyright Â©1998-2002 Semtech Corporation
+ *     DOC8-007-001-DS-112
+ *     http://www.semtech.com/pdf/doc8-007-001-ds.pdf
+ *
+ *
+ * HISTORY:
+ *
+ * 20030626: George G. Davis <gdavis@mvista.com>
+ *      Initially based on the following RidgeRun DSPlinux Version 1.6 files:
+ *             linux-2.4.15-rmk1-dsplinux/arch/arm/dsplinux/hid/omap1510_hid.c
+ *             linux-2.4.15-rmk1-dsplinux/arch/arm/dsplinux/hid/omap1510_hid.h
+ *             linux-2.4.15-rmk1-dsplinux/arch/arm/dsplinux/hid/omap1510_ps2.c
+ *             linux-2.4.15-rmk1-dsplinux/arch/arm/dsplinux/hid/omap1510_spi.c
+ *     All original files above are
+ *             Copyright (C) 2001 RidgeRun, Inc.
+ *             Author: Alex McMains <aam@ridgerun.com>
+ *
+ * 20040812: Thiago Radicchi <trr@dcc.ufmg.br>
+ *      Cleanup of old code from 2.4 driver and some debug code.
+ *      Minor changes in interrupt handling code.
+ *
+ * NOTES:
+ *
+ * 1. This driver does not provide support for setting keyboard/mouse
+ *    configuration parameters. Both devices are managed directly by
+ *    the Juno UR8HC007-001 on behalf of the host. This minimises the
+ *    amount of host processing required to manage HID events and state
+ *    changes, e.g. both keyboard and mouse devices are hot pluggable
+ *    with no host intervention required. However, we cannot customise
+ *    keyboard/mouse settings in this case. So we live with the defaults
+ *    as setup by the Juno UR8HC007-001 whatever they may be.
+ * 2. Keyboard auto repeat does not work. See 1 above. : )
+ *
+ *
+ * TODO:
+ *
+ * 1. Complete DPM/LDM stubs and test.
+ * 2. Add SPI error handling support, i.e. resend, etc.,.
+ * 3. Determine why innovator_hid_interrupt() is called for every
+ *    invocation of Innovator FPGA IRQ demux. It appears that the
+ *    missed Innovator ethernet workaround may be to blame. However,
+ *    it does not adversely affect operation of this driver since we
+ *    check for assertion of ATN prior to servicing the interrupt. If
+ *    ATN is negated, we bug out right away.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/arch/fpga.h>
+
+#undef INNOVATOR_KEYB_DEBUG
+#ifdef INNOVATOR_KEYB_DEBUG
+#define        dbg(format, arg...) printk(KERN_DEBUG "%s:%d: " format , \
+                                  __FUNCTION__ , __LINE__ , ## arg)
+#define        entry() printk(KERN_DEBUG "%s:%d: Entry\n" , __FUNCTION__ , __LINE__)
+#define        exit()  printk(KERN_DEBUG "%s:%d: Exit\n" , __FUNCTION__ , __LINE__)
+#define dump_packet(p, n)                                      \
+       {                                                       \
+               int i;                                          \
+               printk(KERN_DEBUG "%s:%d: %08x:" ,              \
+                      __FUNCTION__ , __LINE__ , (int) p);      \
+               for (i = 0; i < n; i += 1) {                    \
+                       printk(" %02x", (int) p[i]);            \
+               }                                               \
+               printk("\n");                                   \
+       }
+#else
+#define        dbg(format, arg...) do {} while (0)
+#define        entry() do {} while (0)
+#define        exit()  do {} while (0)
+#define dump_packet(p, n) do {} while (0)
+#endif
+
+
+#define        PFX     "innovator_ps2"
+#define err(format, arg...)    printk(KERN_ERR PFX ": " format , ## arg)
+#define info(format, arg...)   printk(KERN_INFO PFX ": " format , ## arg)
+#define warn(format, arg...)   printk(KERN_WARNING PFX ": " format , ## arg)
+
+
+/****************************************************************************/
+
+/*
+ * Synchronous communications timing parameters (Reference [1] pg 7-7)
+ */
+
+#define tMSA   5000    /* -/5ms        _SS to _ATN (master transfer) */
+#define tMAC   100     /* 100us/5ms    _ATN to first clock pulse (master
+                                       transfer) */
+#define tMIB   150     /* 150us/5ms    Beginning of byte transfer to beginning
+                                       of next byte transfer */
+#define tSIB   150     /* 150us/5ms    Beginning of byte transfer to beginning
+                                       of next byte transfer */
+#define tMSP   100     /* -/100us      Last clock pulse of packet to _SS
+                                       de-assertion */
+#define tMNSA  100     /* -/100us      _SS de-assertion to _ATN de-assertion */
+#define tMNEXT 120     /* 120uS/-      _ATN release to _SS re-assertion
+                                       (master transfer) */
+#define        tSAS    5000    /* -/5ms        _ATN to _SS (slave transfer) */
+#define tSSC   100     /* 100us/5ms    _SS to first clock pulse (slave
+                                       transfer) */
+#define tSNA   100     /* -/100us      Last clock pulse of packet to _ATN
+                                       de-assertion */
+#define tSNAS  100     /* -/100us      _ATN release to _SS de-assertion */
+#define tSNEXT 120     /* 120us/-      _SS release to _ATN re-assertion
+                                       (slave transfer) */
+#define tSCK   4       /* 4us/-        Clock period */
+#define tSLOW  2       /* 2us/-        Clock LOW period */
+#define tHOLD  200     /* 200ns/-      Master data hold time */
+#define tSETUP 100     /* 100ns/-      Master data setup Time */
+#define tSSETUP        500     /* -/500ns      Slave data setup time from clock
+                                       falling edge */
+
+
+/*
+ * Protocol Headers (Reference [1], pg. 5-1):
+ */
+
+
+/* Protocols used in commands issued by the host: */
+#define SIMPLE                 0x80    /* Simple commands
+                                        * Common for both host and controller
+                                        * protocol headers.
+                                        */
+#define WRITE_REGISTER_BIT     0x81    /* Write register bit */
+#define READ_REGISTER_BIT      0x82    /* Read register bit */
+#define WRITE_REGISTER         0x83    /* Write register */
+#define READ_REGISTER          0x84    /* Read register */
+#define WRITE_BLOCK            0x85    /* Write block */
+#define READ_BLOCK             0x86    /* Read block */
+
+
+/* Protocols used in responses, reports and alerts issued by the controller: */
+#define REPORT_REGISTER_BIT    0x81    /* Report register bit & event alerts */
+#define REPORT_REGISTER                0x83    /* Report register */
+#define REPORT_BLOCK           0x85    /* Report block */
+#define POINTING_REPORT                0x87    /* Pointing device data report */
+#define KEYBOARD_REPORT                0x88    /* Keyboard device data report */
+
+
+/* Simple Commands (Reference [1], pg 5-3): */
+#define INITIALIZE             0x00    /* Forces the recipient to enter the
+                                        * known default power-on state.
+                                        */
+#define INITIALIZATION_COMPLETE        0x01    /* Issued as a hand-shake response only
+                                        * to the "Initialize" command.
+                                        */
+#define RESEND_REQUEST         0x05    /* Issued upon error in the reception
+                                        * of a package. The recipient resends
+                                        * the last transmitted packet.
+                                        */
+
+/* Register offsets (Reference [1], pg 6-1 thru 6-9): */
+
+#define REG_PM_COMM            0
+#define REG_PM_STATUS          1
+#define REG_PAGENO             255
+
+/* Power management bits ((Reference [1], pg 6-10): */
+
+#define SUS_STATE              0x2     /* in REG_PM_COMM */
+
+/* Miscellaneous constants: */
+
+#define X_MSB_SHIFT    (8-4)
+#define X_MSB_MASK     (3<<4)
+#define Y_MSB_SHIFT    (8-6)
+#define Y_MSB_MASK     (3<<6)
+
+
+#define JUNO_BLOCK_SIZE     32
+#define JUNO_BUFFER_SIZE    256
+
+
+/*
+ * Errors:
+ */
+
+#define E_BAD_HEADER   1
+#define E_BAD_LRC      2
+#define E_ZERO_BYTES   3
+#define E_BAD_VALUE    4
+#define E_BAD_MODE     5
+#define E_REPORT_MODE  6
+#define E_BAD_ACK      7
+#define E_BAD_DEVICE_ID        8
+#define E_PKT_SZ       9
+
+
+/*
+ * Host/Controller Command/Response Formats:
+ */
+
+typedef struct _simple_t {
+       u8 header;
+       u8 cmd_code;
+       u8 LRC;
+} __attribute__ ((packed)) simple_t;
+
+typedef struct _write_bit_t {
+       u8 header;
+       u8 offset;
+       u8 value_bit;
+       u8 LRC;
+} __attribute__ ((packed)) write_bit_t;
+
+typedef struct _read_bit_t {
+       u8 header;
+       u8 offset;
+       u8 bit;
+       u8 LRC;
+} __attribute__ ((packed)) read_bit_t;
+
+typedef struct _write_reg_t {
+       u8 header;
+       u8 offset;
+       u8 value;
+       u8 LRC;
+} __attribute__ ((packed)) write_reg_t;
+
+typedef struct _read_reg_t {
+       u8 header;
+       u8 offset;
+       u8 LRC;
+} __attribute__ ((packed)) read_reg_t;
+
+typedef struct _write_block_t {
+       u8 header;
+       u8 offset;
+       u8 length;
+       u8 block[JUNO_BLOCK_SIZE + 1]; /* Hack: LRC is last element of block[] */
+} __attribute__ ((packed)) write_block_t;
+
+typedef struct _read_block_t {
+       u8 header;
+       u8 offset;
+       u8 length;
+       u8 LRC;
+} __attribute__ ((packed)) read_block_t;
+
+typedef struct _report_bit_t {
+       u8 header;
+       u8 offset;
+       u8 value_bit;
+       u8 LRC;
+} __attribute__ ((packed)) report_bit_t;
+
+typedef struct _report_reg_t {
+       u8 header;
+       u8 offset;
+       u8 value;
+       u8 LRC;
+} __attribute__ ((packed)) report_reg_t;
+
+typedef struct _report_block_t {
+       u8 header;
+       u8 offset;
+       u8 length;
+       u8 block[32];
+       u8 LRC;
+} __attribute__ ((packed)) report_block_t;
+
+typedef struct _mse_report_t {
+       u8 header;
+       u8 buttons;
+       u8 Xdisplacement;
+       u8 Ydisplacement;
+       u8 Zdisplacement;
+       u8 LRC;
+} __attribute__ ((packed)) mse_report_t;
+
+typedef struct _kdb_report_t {
+       u8 header;
+       u8 keynum;              /* up > 0x80, down < 0x7E, all keys up 0x00 */
+       u8 LRC;
+} __attribute__ ((packed)) kdb_report_t;
+
+
+static u8 buffer[JUNO_BUFFER_SIZE];
+static u8 block[JUNO_BLOCK_SIZE];
+
+static void do_hid_tasklet(unsigned long);
+DECLARE_TASKLET(hid_tasklet, do_hid_tasklet, 0);
+static struct innovator_hid_dev *hid;
+static spinlock_t innovator_fpga_hid_lock = SPIN_LOCK_UNLOCKED;
+static atomic_t innovator_fpga_hid_busy = ATOMIC_INIT(0);
+
+struct innovator_hid_dev {
+       struct input_dev mouse, keyboard;
+       int open;
+       int irq_enabled;
+};
+
+/****************************************************************************/
+
+/*
+ * Low-level TI Innovator/OMAP1510 FPGA HID SPI interface helper functions:
+ */
+
+static u8
+innovator_fpga_hid_rd(void)
+{
+       u8 val = inb(INNOVATOR_FPGA_HID_SPI);
+       return val;
+}
+
+static void
+innovator_fpga_hid_wr(u8 val)
+{
+       outb(val, INNOVATOR_FPGA_HID_SPI);
+}
+
+static void
+innovator_fpga_hid_frob(u8 mask, u8 val)
+{
+       unsigned long flags;
+       local_irq_save(flags);
+       innovator_fpga_hid_wr((innovator_fpga_hid_rd() & ~mask) | val);
+       local_irq_restore(flags);
+}
+
+static void
+innovator_fpga_hid_set_bits(u8 x)
+{
+       innovator_fpga_hid_frob(x, x);
+}
+
+static void
+innovator_fpga_hid_clear_bits(u8 x)
+{
+       innovator_fpga_hid_frob(x, 0);
+}
+
+static void
+SS(int value)
+{
+       innovator_fpga_hid_frob(OMAP1510_FPGA_HID_nSS, value ? OMAP1510_FPGA_HID_nSS : 0);
+}
+
+static void
+SCLK(int value)
+{
+       innovator_fpga_hid_frob(OMAP1510_FPGA_HID_SCLK, value ? OMAP1510_FPGA_HID_SCLK : 0);
+}
+
+static void
+MOSI(int value)
+{
+       innovator_fpga_hid_frob(OMAP1510_FPGA_HID_MOSI, value ? OMAP1510_FPGA_HID_MOSI : 0);
+}
+
+static u8
+MISO(void)
+{
+       return ((innovator_fpga_hid_rd() & OMAP1510_FPGA_HID_MISO) ? 1 : 0);
+}
+
+static u8 
+ATN(void)
+{
+       return ((innovator_fpga_hid_rd() & OMAP1510_FPGA_HID_ATN) ? 1 : 0);
+}
+
+static int
+wait_for_ATN(int assert, int timeout)
+{
+       do {
+               if (ATN() == assert)
+                       return 0;
+               udelay(1);
+       } while (timeout -= 1);
+       return -1;
+}
+
+static u8
+innovator_fpga_hid_xfer_byte(u8 xbyte)
+{
+       int i;
+       u8 rbyte;
+
+       for (rbyte = 0, i = 7; i >= 0; i -= 1) {
+               SCLK(0);
+               MOSI((xbyte >> i) & 1);
+               udelay(tSLOW);
+               SCLK(1);
+               rbyte = (rbyte << 1) | MISO();
+               udelay(tSLOW);
+       }
+
+       return rbyte;
+}
+
+static void
+innovator_fpga_hid_reset(void)
+{
+       innovator_fpga_hid_wr(OMAP1510_FPGA_HID_SCLK | OMAP1510_FPGA_HID_MOSI);
+       mdelay(1);
+       innovator_fpga_hid_set_bits(OMAP1510_FPGA_HID_RESETn);
+}
+
+
+/*****************************************************************************
+
+  Refer to Reference [1], Chapter 7 / Low-level communications, Serial
+  Peripheral Interface (SPI) implementation Host (master) packet
+  transmission timing, pg. 7-3, for timing and implementation details
+  for spi_xmt().
+
+ *****************************************************************************/
+
+int
+spi_xmt(u8 * p, u8 n)
+{
+       unsigned long flags;
+
+       dump_packet(p, n);
+       local_irq_save(flags);
+       disable_irq(OMAP1510_INT_FPGA_ATN);
+
+       if (ATN()) {
+               /* Oops, we have a collision. */
+               enable_irq(OMAP1510_INT_FPGA_ATN);
+               local_irq_restore(flags);
+               dbg("Protocol error: ATN is asserted\n");
+               return -EAGAIN;
+       }
+
+       SS(1);
+
+       if (wait_for_ATN(1, tMSA) < 0) {
+               SS(0);
+               enable_irq(OMAP1510_INT_FPGA_ATN);
+               local_irq_restore(flags);
+               dbg("timeout waiting for ATN assertion\n");
+               return -EREMOTEIO;
+       }
+
+       udelay(tMAC);
+
+       while (n--) {
+               innovator_fpga_hid_xfer_byte(*p++);
+               if (n) {
+                       udelay(tMIB - 8 * tSCK);
+               }
+       }
+
+       MOSI(1);        /* Set MOSI to idle high. */
+
+       /* NOTE: The data sheet does not specify a minimum delay
+        * here. But innovator_fpga_hid_xfer_byte() gives us a half-clock
+        * delay (tSLOW) after the last bit is sent. So I'm happy with
+        * that.
+        */
+
+       SS(0);
+
+       if (wait_for_ATN(0, tMNSA) < 0) {
+               enable_irq(OMAP1510_INT_FPGA_ATN);
+               local_irq_restore(flags);
+               dbg("timeout waiting for ATN negation\n");
+               return -EREMOTEIO;
+       }
+
+       udelay(tMNEXT);
+       enable_irq(OMAP1510_INT_FPGA_ATN);
+       local_irq_restore(flags);
+       return 0;
+}
+
+
+/*****************************************************************************
+
+  Refer to Reference [1],  Chapter 7 / Low-level communications, Serial
+  Peripheral Interface (SPI) implementation, Slave packet transmission
+  timing, pg. 7-5, for timing and implementation details for spi_rcv().
+
+ *****************************************************************************/
+
+int
+spi_rcv(u8 * p, int len)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       if (len > 256) {
+               /* Limit packet size to something reasonable */
+               return -1;
+       }
+
+       local_irq_save(flags);
+
+       if (wait_for_ATN(1, tMSA) < 0) {
+               local_irq_restore(flags);
+               dbg("Protocol error: ATN is not asserted\n");
+               return -EREMOTEIO;
+       }
+
+       SS(1);
+
+       udelay(tSSC);
+
+       while (ATN()) {
+               if (ret >= len) {
+                       err("over run error\n");
+                       ret = -1;
+                       break;
+               }
+               p[ret++] = innovator_fpga_hid_xfer_byte(0xff);
+               udelay(tSNA);   /* Wait long enough to detect negation of ATN
+                                * after last clock pulse of packet.
+                                *
+                                * NOTE: Normally, we need a minimum delay of
+                                *       tSIB between the start of one byte
+                                *       and the start of the next. However,
+                                *       we also need to wait long enough
+                                *       for the USAR to negate ATN before
+                                *       starting the next byte. So we use
+                                *       max(tSIB - 8 * tSCK, tSNA) here to
+                                *       satisfy both constraints.
+                                */
+       }
+
+       SS(0);  /* NOTE: The data sheet does not specify a minimum delay
+                * here. But innovator_fpga_hid_xfer_byte() gives us a
+                * half-clock delay (tSLOW) after the last bit is sent. So
+                * I'm happy with that (rather than no delay at all : ).
+                */
+
+
+       udelay(tSNEXT); /* This isn't quite right. Assertion of ATN after
+                        * negation of SS is an USAR timing constraint.
+                        * What we need here is a spec for the minimum
+                        * delay from SS negation to SS assertion. But
+                        * for now, just use this brain dead delay.
+                        */
+
+       local_irq_restore(flags);
+
+       if (ret > 0) {
+               dump_packet(p, ret);
+       }
+
+       return ret;
+}
+
+
+/*****************************************************************************
+  Calculate Host/Controller Command/Response Longitudinal Redundancy Check (LRC)
+
+  The algorithm implemented in calculate_LRC() below is taken directly from
+  the reference [1], Chapter 7 / Low-level communications, LRC (Longitudinal
+  Redundancy Check), pg 5-10.
+
+ *****************************************************************************/
+
+static u8
+calculate_LRC(u8 * p, int n)
+{
+       u8 LRC;
+       int i;
+
+       /*
+        * Init the LRC using the first two message bytes.
+        */
+       LRC = p[0] ^ p[1];
+
+       /*
+        * Update the LRC using the remainder of the p.
+        */
+       for (i = 2; i < n; i++)
+               LRC ^= p[i];
+
+       /*
+        * If the MSB is set then clear the MSB and change the next
+        * most significant bit
+        */
+       if (LRC & 0x80)
+               LRC ^= 0xC0;
+
+       return LRC;
+}
+
+
+/*
+ * Controller response helper functions:
+ */
+
+static inline int
+report_mouse(mse_report_t * p, int n)
+{
+       if (p->header != POINTING_REPORT)
+               return -E_BAD_HEADER;
+
+       if (n != sizeof(mse_report_t))
+               return -E_PKT_SZ;
+
+       return (p->LRC != calculate_LRC((u8 *) p, sizeof(mse_report_t) - 1)) ?
+               -E_BAD_LRC : POINTING_REPORT;
+}
+
+static inline int
+report_keyboard(kdb_report_t * p, int n)
+{
+       if (p->header != KEYBOARD_REPORT)
+               return -E_BAD_HEADER;
+
+       if (n != sizeof(kdb_report_t))
+               return -E_PKT_SZ;
+
+       return (p->LRC != calculate_LRC((u8 *) p, sizeof(kdb_report_t) - 1)) ?
+               -E_BAD_LRC : KEYBOARD_REPORT;
+}
+
+
+/*
+ * Miscellaneous helper functions:
+ */
+
+static inline int
+report_type(u8 * type)
+{
+       /* check the header to find out what kind of report it is */
+       if ((*type) == KEYBOARD_REPORT)
+               return KEYBOARD_REPORT;
+       else if ((*type) == POINTING_REPORT)
+               return POINTING_REPORT;
+       else
+               return -E_BAD_HEADER;
+}
+
+static inline int
+report_async(void * p, int n)
+{
+       int ret;
+
+       if ((ret = spi_rcv((u8 *) p, n)) < 0)
+               return ret;
+
+       if (report_type((u8 *) p) == POINTING_REPORT)
+               ret = report_mouse((mse_report_t *) p, ret);
+       else if (report_type((u8 *) p) == KEYBOARD_REPORT)
+               ret = report_keyboard((kdb_report_t *) p, ret);
+
+       return ret;
+}
+
+static int
+verify_init(u8 * p)
+{
+       return (((simple_t *)p)->cmd_code == 0x01) ? 0 : -1;
+}
+
+
+/*
+ * Host command helper functions:
+ */
+
+#if    0
+/* REVISIT/TODO: Wrapper for command/response with resend handing. */
+static int
+spi_xfer(u8 * optr, u8 osz, u8 * iptr, u8 isz)
+{
+       static u8 buf[256];
+       int ret;
+       int xretries = 3;
+
+       do {
+               if (optr != NULL && osz) {
+                       do {
+                               ret = spi_xmt((u8 *) optr, osz);
+                       } while (ret < 0);
+               }
+
+               ret = spi_rcv((u8 *) buf, 256);
+
+               if (ret == -EREMOTEIO) {
+                       if (iptr == NULL) {
+                               break;
+                       }
+               }
+       } while (xretries--);
+
+       return ret;
+}
+#endif
+
+/* REVISIT: Enable these when/if additional Juno features are required. */
+static inline int
+simple(u8 cmd)
+{
+       static simple_t p;
+       int ret;
+
+       p.header = SIMPLE;
+       p.cmd_code = cmd;
+       p.LRC = calculate_LRC((u8 *) & p, sizeof(p) - 1);
+
+       if ((ret = spi_xmt((u8 *) & p, sizeof(p))) < 0)
+               return ret;
+
+       if ((ret = spi_rcv((u8 *) & p, sizeof(p))) < 0)
+               return ret;
+
+       if (ret == 0)
+               return -E_ZERO_BYTES;
+
+       if (ret != sizeof(p))
+               return -E_PKT_SZ;
+
+       if (p.header != SIMPLE)
+               return -E_BAD_HEADER;
+
+       if (p.LRC != calculate_LRC((u8 *) & p, sizeof(p) - 1))
+               return -E_BAD_LRC;
+
+       /* REVISIT: Need to check or return response code here? */
+}
+
+static inline int
+write_bit(u8 offset, u8 bit, u8 value)
+{
+       static write_bit_t p;
+
+       p.header = WRITE_REGISTER_BIT;
+       p.offset = offset;
+       p.value_bit = (bit << 1) | (value & 1);
+       p.LRC = calculate_LRC((u8 *) & p, sizeof(p) - 1);
+
+       return spi_xmt((u8 *) & p, sizeof(p));
+}
+
+static inline int
+read_bit(u8 offset, u8 bit, u8 * data)
+{
+       static read_bit_t p;
+       static report_bit_t q;
+       int ret;
+
+       p.header = READ_REGISTER_BIT;
+       p.offset = offset;
+       p.bit = bit;
+       p.LRC = calculate_LRC((u8 *) & p, sizeof(p) - 1);
+
+       if ((ret = spi_xmt((u8 *) & p, sizeof(p))) < 0)
+               return ret;
+
+       if ((ret = spi_rcv((u8 *) & q, sizeof(q))) < 0)
+               return ret;
+
+       if (ret == 0)
+               return -E_ZERO_BYTES;
+
+       if (ret != sizeof(q))
+               return -E_PKT_SZ;
+
+       if (q.header != REPORT_REGISTER_BIT)
+               return -E_BAD_HEADER;
+
+       if (q.LRC != calculate_LRC((u8 *) & q, sizeof(q) - 1))
+               return -E_BAD_LRC;
+
+       *data = q.value_bit;
+
+       return 0;
+}
+
+static inline int
+write_reg(u8 offset, u8 value)
+{
+       static write_reg_t p;
+
+       p.header = WRITE_REGISTER;
+       p.offset = offset;
+       p.value = value;
+       p.LRC = calculate_LRC((u8 *) & p, sizeof(p) - 1);
+
+       return spi_xmt((u8 *) & p, sizeof(p));
+}
+
+static inline int
+read_reg(u8 offset, u8 * data)
+{
+       static read_reg_t p;
+       static report_reg_t q;
+       int ret;
+
+       p.header = READ_REGISTER;
+       p.offset = offset;
+       p.LRC = calculate_LRC((u8 *) & p, sizeof(p) - 1);
+
+       if ((ret = spi_xmt((u8 *) & p, sizeof(p))) < 0)
+               return ret;
+
+       if ((ret = spi_rcv((u8 *) & q, sizeof(q))) < 0)
+               return ret;
+
+       if (ret == 0)
+               return -E_ZERO_BYTES;
+
+       if (ret != sizeof(q))
+               return -E_PKT_SZ;
+
+       if (q.header != REPORT_REGISTER)
+               return -E_BAD_HEADER;
+
+       if (q.LRC != calculate_LRC((u8 *) & q, sizeof(q) - 1))
+               return -E_BAD_LRC;
+
+       *data = q.value;
+
+       return 0;
+}
+
+static inline int
+write_block(u8 offset, u8 length, u8 * block)
+{
+       static write_block_t p;
+
+       p.header = WRITE_BLOCK;
+       p.offset = offset;
+       p.length = length;
+       memcpy(&p.block, block, length);
+       p.block[length] = calculate_LRC((u8 *) & p, 3 + length);
+
+       return spi_xmt((u8 *) & p, 4 + length);
+}
+
+static inline int
+read_block(u8 offset, u8 length, u8 * buf)
+{
+       static read_block_t p;
+       static report_block_t q;
+       int ret;
+
+       p.header = READ_BLOCK;
+       p.offset = offset;
+       p.length = length;
+       p.LRC = calculate_LRC((u8 *) & p, sizeof(p) - 1);
+
+       if ((ret = spi_xmt((u8 *) & p, sizeof(p))) < 0)
+               return ret;
+
+       if ((ret = spi_rcv((u8 *) & q, sizeof(q))) < 0)
+               return ret;
+
+       if (ret == 0)
+               return -E_ZERO_BYTES;
+
+       if (ret != sizeof(4 + q.length))
+               return -E_PKT_SZ;
+
+       if (q.header != REPORT_BLOCK)
+               return -E_BAD_HEADER;
+
+       if (q.block[q.length] != calculate_LRC((u8 *) & q, 3 + q.length))
+               return -E_BAD_LRC;
+
+       if (length != q.length)
+               return -E_PKT_SZ;
+
+       memcpy(buf, &q.block, length);
+
+       return 0;
+}
+
+#ifdef INNOVATOR_KEYB_DEBUG
+static void
+ctrl_dump_regs(void)
+{
+       int i;
+       int n;
+
+       for (i = 0; i < 256; i += 8) {
+               read_block(i, 16, buffer);
+               mdelay(1);
+       }
+}
+#endif
+
+/*****************************************************************************/
+
+static void
+process_pointing_report(struct innovator_hid_dev *hid, u8 * buffer)
+{
+       static int prev_x, prev_y, prev_btn;
+       int x, y, btn;
+
+       if (buffer[1] & (1 << 3)) {
+               /* relative pointing device report */
+               x = buffer[2];
+               y = buffer[3];
+
+               /* check the sign and convert from 2's complement if negative */
+               if (buffer[1] & (1<<4))
+                       x = ~(-x) - 255;
+
+               /* input driver wants -y */
+               if (buffer[1] & (1<<5))
+                       y = -(~(-y) - 255);
+               else
+                       y = -y;
+
+               input_report_key(&hid->mouse,
+                                BTN_LEFT, buffer[1] & (1<<0));
+               input_report_key(&hid->mouse,
+                                BTN_RIGHT, buffer[1] & (1<<1));
+               input_report_key(&hid->mouse,
+                                BTN_MIDDLE, buffer[1] & (1<<2));
+               input_report_rel(&hid->mouse, REL_X, x);
+               input_report_rel(&hid->mouse, REL_Y, y);
+       } else {
+               /* REVISIT: Does this work? */
+               /* absolute pointing device report */
+               x = buffer[2] + ((buffer[1] & X_MSB_MASK) << X_MSB_SHIFT);
+               y = buffer[3] + ((buffer[1] & Y_MSB_MASK) << Y_MSB_SHIFT);
+               btn = buffer[1] & (1<<0);
+
+               if ((prev_x == x) && (prev_y == y)
+                   && (prev_btn == btn))
+                       return;
+
+               input_report_key(&hid->mouse, BTN_LEFT, btn);
+               input_report_abs(&hid->mouse, ABS_X, x);
+               input_report_abs(&hid->mouse, ABS_Y, y);
+               prev_x = x;
+               prev_y = y;
+               prev_btn = btn;
+       }
+       input_sync(&hid->mouse);
+       dbg("HID X: %d Y: %d Functions: %x\n", x, y, buffer[1]);
+}
+
+/*
+ * Reference [1], Appendix A, Semtech standard PS/2 key number definitions,
+ * pgs. A-1 through A-3. The following table lists standard PS/2 key numbers
+ * used by the Juno® 01 keyboard manager.
+ *
+ * NOTES:
+ * 1. The following table indices are E0 codes which require special handling:
+ *     53..62, 77..78, 94, 96, 100, 102..104, 108..110
+ * 2. The following table indices are E1 codes which require special handling:
+ *     101
+ */
+
+static unsigned char usar2scancode[128] = {
+       0x00, 0x29, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+       0x18, 0x19, 0x1a, 0x1b, 0x2b, 0x1e, 0x1f, 0x20,
+       0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+       0x1c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
+       0x33, 0x34, 0x35, 0x39, 0x01, 0x52, 0x53, 0x4b,
+       0x47, 0x4f, 0x48, 0x50, 0x49, 0x51, 0x4d, 0x37,
+       0x4e, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47,
+       0x48, 0x49, 0x52, 0x53, 0x4a, 0x1c, 0x35, 0x3b,
+       0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
+       0x44, 0x57, 0x58, 0x2a, 0x36, 0x38, 0x38, 0x1d,
+       0x1d, 0x3a, 0x45, 0x46, 0x2a, 0x1d, 0x5b, 0x5c,
+       0x5d, 0xff, 0x00, 0x00, 0x5e, 0x5f, 0x63, 0x70,
+       0x7b, 0x79, 0x7d, 0x73, 0x5b, 0x5c, 0x5d, 0x63,
+       0x65, 0x66, 0x68, 0x69, 0x6b, 0x56, 0x54, 0x00
+};
+
+/*
+ * The following are bit masks used to encode E0 scan codes which
+ * require special handling. However, scan codes 100 and 101 are
+ * excludable here since they each require unique multi-byte scan
+ * code translations and are therefore dealt with individually via
+ * handle_print_scr() and handle_pause() respectively below.
+ */
+
+static unsigned long int e0_codes1 = 0x030003ff; /* scan codes 53..84 */
+static unsigned long int e0_codes2 = 0x038e0a00; /* scan codes 85..116 */
+
+static void
+handle_print_scr(int up)
+{
+       if (up) {
+               input_report_key(&hid->keyboard, 0xe0, 1);
+               input_report_key(&hid->keyboard, 0xb7, 1);
+               input_report_key(&hid->keyboard, 0xe0, 1);
+               input_report_key(&hid->keyboard, 0xaa, 1);
+       } else {
+               input_report_key(&hid->keyboard, 0xe0, 0);
+               input_report_key(&hid->keyboard, 0x2a, 0);
+               input_report_key(&hid->keyboard, 0xe0, 0);
+               input_report_key(&hid->keyboard, 0x37, 0);
+       }
+}
+
+static void
+handle_pause(void)
+{
+       input_report_key(&hid->keyboard, 0xe1, 0);
+       input_report_key(&hid->keyboard, 0x1d, 0);
+       input_report_key(&hid->keyboard, 0x45, 0);
+       input_report_key(&hid->keyboard, 0xe1, 0);
+       input_report_key(&hid->keyboard, 0x9d, 0);
+       input_report_key(&hid->keyboard, 0xc5, 0);
+}
+
+static void
+process_keyboard_report(struct innovator_hid_dev *hid, u8 * buffer)
+{
+       unsigned char ch = buffer[1] & 0x7f;
+       int up = buffer[1] & 0x80 ? 1 : 0;
+       int is_e0 = 0;
+
+       if ((ch == 106) || (ch == 107))
+               return;         /* no code */
+
+       if (ch == 100) {
+               handle_print_scr(up);
+               return;
+       }
+
+       if (ch == 101) {
+               handle_pause();
+               return;
+       }
+
+       if ((ch >= 53) && (ch <= 84)) {
+               /* first block of e0 codes */
+               is_e0 = e0_codes1 & (1 << (ch - 53));
+       } else if ((ch >= 85) && (ch <= 116)) {
+               /* second block of e0 codes */
+               is_e0 = e0_codes2 & (1 << (ch - 85));
+       }
+
+       if (is_e0) {
+               input_report_key(&hid->keyboard, 0xe0, !up);
+       }
+       input_report_key(&hid->keyboard, usar2scancode[ch], !up);
+       input_sync(&hid->keyboard);
+}
+
+static irqreturn_t
+innovator_hid_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       if (ATN()) {
+               disable_irq(OMAP1510_INT_FPGA_ATN);
+               tasklet_schedule(&hid_tasklet);
+       }
+       return IRQ_HANDLED;
+}
+
+static void
+do_hid_tasklet(unsigned long unused)
+{
+       int ret;
+       if ((ret = report_async(buffer, 256)) == -1) {
+               dbg("Error: Bad Juno return value: %d\n", ret);
+       } else if (ret == KEYBOARD_REPORT) {
+               process_keyboard_report(hid, buffer);
+       } else if (ret == POINTING_REPORT) {
+               process_pointing_report(hid, buffer);
+       } else {
+               dbg("ERROR: bad report\n");
+       }
+       enable_irq(OMAP1510_INT_FPGA_ATN);
+}
+
+static int
+innovator_hid_open(struct input_dev *dev)
+{
+       if (hid->open++)
+               return 0;
+
+       if (request_irq(OMAP1510_INT_FPGA_ATN, (void *) innovator_hid_interrupt,
+                       SA_INTERRUPT, PFX, hid) < 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static void
+innovator_hid_close(struct input_dev *dev)
+{
+       if (!--hid->open)
+               return;
+
+       if (hid == NULL)
+               return;
+
+       kfree(hid);
+}
+
+static int innovator_ps2_remove(struct device *dev)
+{
+       return 0;
+}
+
+static void innovator_ps2_device_release(struct device *dev)
+{
+       /* Nothing */
+}
+
+static int innovator_ps2_suspend(struct device *dev, pm_message_t state)
+{
+       u8 pmcomm;
+
+       /*
+        * Set SUS_STATE in REG_PM_COMM (Page 0 R0).  This will cause
+        * PM_MOD bits of REG_PM_STATUS to show suspended state,
+        * but the SUS_STAT bit of REG_PM_STATUS will continue to
+        * reflect the state of the _HSUS pin.
+        */
+
+       if (write_reg(REG_PAGENO, 0) < 0)
+               printk("ps2 suspend: write_reg REG_PAGENO error\n");
+
+       if (read_reg(REG_PM_COMM, &pmcomm) < 0)
+               printk("ps2 suspend: read_reg REG_PM_COMM error\n");
+               
+       if (write_reg(REG_PM_COMM, pmcomm | SUS_STATE) < 0)
+               printk("ps2 suspend: write_reg REG_PM_COMM error\n");
+
+       return 0;
+}
+
+static int innovator_ps2_resume(struct device *dev)
+{
+       u8 pmcomm;
+
+       /*
+        * Clear SUS_STATE from REG_PM_COMM (Page 0 R0).
+        */
+
+       if (write_reg(REG_PAGENO, 0) < 0)
+               printk("ps2 resume: write_reg REG_PAGENO error\n");
+
+       if (read_reg(REG_PM_COMM, &pmcomm) < 0)
+               printk("ps2 resume: read_reg REG_PM_COMM error\n");
+
+       if (write_reg(REG_PM_COMM, pmcomm & ~SUS_STATE) < 0)
+               printk("ps2 resume: write_reg REG_PM_COMM error\n");
+
+       return 0;
+}
+
+static struct device_driver innovator_ps2_driver = {
+       .name           = "innovator_ps2",
+       .bus            = &platform_bus_type,
+       .remove         = innovator_ps2_remove,
+       .suspend        = innovator_ps2_suspend,
+       .resume         = innovator_ps2_resume,
+};
+
+static struct platform_device innovator_ps2_device = {
+       .name           = "ps2",
+       .id             = -1,
+       .dev = {
+               .driver         = &innovator_ps2_driver,
+               .release        = innovator_ps2_device_release,
+       },
+};
+
+static int __init
+innovator_kbd_init(void)
+{
+       int i;
+       info("Innovator PS/2 keyboard/mouse driver v1.0\n");
+
+       innovator_fpga_hid_reset();
+
+       if ((hid = kmalloc(sizeof(struct innovator_hid_dev),
+            GFP_KERNEL)) == NULL) {
+               warn("unable to allocate space for HID device\n");
+               return -ENOMEM;
+       }
+
+       /* setup the mouse */
+       memset(hid, 0, sizeof(struct innovator_hid_dev));
+       hid->mouse.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+       hid->mouse.keybit[LONG(BTN_MOUSE)] =
+           BIT(BTN_LEFT) | BIT(BTN_RIGHT) |
+           BIT(BTN_MIDDLE) | BIT(BTN_TOUCH);
+       hid->mouse.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+       hid->mouse.private = hid;
+       hid->mouse.open = innovator_hid_open;
+       hid->mouse.close = innovator_hid_close;
+       hid->mouse.name = "innovator_mouse";
+       hid->mouse.id.bustype = 0;
+       hid->mouse.id.vendor = 0;
+       hid->mouse.id.product = 0;
+       hid->mouse.id.version = 0;
+       hid->keyboard.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+        init_input_dev(&hid->keyboard);
+        hid->keyboard.keycodesize = sizeof(unsigned char);
+        hid->keyboard.keycodemax = ARRAY_SIZE(usar2scancode);
+       for(i = 0; i < 128; i++)
+               set_bit(usar2scancode[i], hid->keyboard.keybit); 
+       hid->keyboard.private = hid;
+       hid->keyboard.open = innovator_hid_open;
+       hid->keyboard.close = innovator_hid_close;
+       hid->keyboard.name = "innovator_keyboard";
+       hid->keyboard.id.bustype = 0;
+       hid->keyboard.id.vendor = 0;
+       hid->keyboard.id.product = 0;
+       hid->keyboard.id.version = 0;
+       input_register_device(&hid->mouse);
+       input_register_device(&hid->keyboard);
+       innovator_hid_open(&hid->mouse);
+       innovator_hid_open(&hid->keyboard);
+
+       if (driver_register(&innovator_ps2_driver) != 0)
+               printk(KERN_ERR "Driver register failed for innovator_ps2\n");
+
+       if (platform_device_register(&innovator_ps2_device) != 0) {
+               printk(KERN_ERR "Device register failed for ps2\n");
+               driver_unregister(&innovator_ps2_driver);
+       }
+
+#ifdef INNOVATOR_KEYB_DEBUG
+       ctrl_dump_regs();
+#endif
+       return 0;
+}
+
+static void __exit
+innovator_kbd_exit(void)
+{
+       input_unregister_device(&hid->mouse);
+       input_unregister_device(&hid->keyboard);
+       free_irq(OMAP1510_INT_FPGA_ATN, hid);
+       if (hid != NULL)
+               kfree(hid);
+       driver_unregister(&innovator_ps2_driver);
+       platform_device_unregister(&innovator_ps2_device);
+       return;
+}
+
+module_init(innovator_kbd_init);
+module_exit(innovator_kbd_exit);
+
+MODULE_AUTHOR("George G. Davis <gdavis@mvista.com>");
+MODULE_DESCRIPTION("Innovator PS/2 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
new file mode 100644 (file)
index 0000000..5fe8e7a
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * linux/drivers/char/omap-keypad.c
+ *
+ * OMAP Keypad Driver
+ *
+ * Copyright (C) 2003 Nokia Corporation
+ * Written by Timo Teräs <ext-timo.teras@nokia.com>
+ *
+ * Added support for H2 & H3 Keypad
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/mach-types.h>
+#include <asm/arch/mux.h>
+
+#undef NEW_BOARD_LEARNING_MODE
+
+static void omap_kp_tasklet(unsigned long);
+static void omap_kp_timer(unsigned long);
+
+static struct input_dev omap_kp_dev;
+static unsigned char keypad_state[8];
+static unsigned int keypad_irq = INT_KEYBOARD;
+
+static struct timer_list kp_timer;
+DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
+
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+
+static int h2_keymap[] = {
+       KEY(0, 0, KEY_LEFT),
+       KEY(0, 1, KEY_RIGHT),
+       KEY(0, 2, KEY_3),
+       KEY(0, 3, KEY_F10),
+       KEY(0, 4, KEY_F5),
+       KEY(0, 5, KEY_9),
+       KEY(1, 0, KEY_DOWN),
+       KEY(1, 1, KEY_UP),
+       KEY(1, 2, KEY_2),
+       KEY(1, 3, KEY_F9),
+       KEY(1, 4, KEY_F7),
+       KEY(1, 5, KEY_0),
+       KEY(2, 0, KEY_ENTER),
+       KEY(2, 1, KEY_6),
+       KEY(2, 2, KEY_1),
+       KEY(2, 3, KEY_F2),
+       KEY(2, 4, KEY_F6),
+       KEY(2, 5, KEY_HOME),
+       KEY(3, 0, KEY_8),
+       KEY(3, 1, KEY_5),
+       KEY(3, 2, KEY_F12),
+       KEY(3, 3, KEY_F3),
+       KEY(3, 4, KEY_F8),
+       KEY(3, 5, KEY_END),
+       KEY(4, 0, KEY_7),
+       KEY(4, 1, KEY_4),
+       KEY(4, 2, KEY_F11),
+       KEY(4, 3, KEY_F1),
+       KEY(4, 4, KEY_F4),
+       KEY(4, 5, KEY_ESC),
+       KEY(5, 0, KEY_F13),
+       KEY(5, 1, KEY_F14),
+       KEY(5, 2, KEY_F15),
+       KEY(5, 3, KEY_F16),
+       KEY(5, 4, KEY_SLEEP),
+       0
+};
+
+static int test_keymap[] = {
+       KEY(0, 0, KEY_F4),
+       KEY(1, 0, KEY_LEFT),
+       KEY(2, 0, KEY_F1),
+       KEY(0, 1, KEY_DOWN),
+       KEY(1, 1, KEY_ENTER),
+       KEY(2, 1, KEY_UP),
+       KEY(0, 2, KEY_F3),
+       KEY(1, 2, KEY_RIGHT),
+       KEY(2, 2, KEY_F2),
+       0
+};
+
+static int innovator_keymap[] = {
+       KEY(0, 0, KEY_F1),
+       KEY(0, 3, KEY_DOWN),
+       KEY(1, 1, KEY_F2),
+       KEY(1, 2, KEY_RIGHT),
+       KEY(2, 0, KEY_F3),
+       KEY(2, 1, KEY_F4),
+       KEY(2, 2, KEY_UP),
+       KEY(3, 2, KEY_ENTER),
+       KEY(3, 3, KEY_LEFT),
+       0
+};
+
+static int osk_keymap[] = {
+       KEY(0, 0, KEY_F1),
+       KEY(0, 3, KEY_UP),
+       KEY(1, 1, KEY_LEFTCTRL),
+       KEY(1, 2, KEY_LEFT),
+       KEY(2, 0, KEY_SPACE),
+       KEY(2, 1, KEY_ESC),
+       KEY(2, 2, KEY_DOWN),
+       KEY(3, 2, KEY_ENTER),
+       KEY(3, 3, KEY_RIGHT),
+       0 
+}; 
+
+static int p2_keymap[] = {
+       KEY(0,0,KEY_UP),
+       KEY(0,1,KEY_RIGHT),
+       KEY(0,2,KEY_LEFT),
+       KEY(0,3,KEY_DOWN),
+       KEY(0,4,KEY_CENTER),
+       KEY(0,5,KEY_0_5),
+       KEY(1,0,KEY_SOFT2),
+       KEY(1,1,KEY_SEND),
+       KEY(1,2,KEY_END),
+       KEY(1,3,KEY_VOLUMEDOWN),
+       KEY(1,4,KEY_VOLUMEUP),
+       KEY(1,5,KEY_RECORD),
+       KEY(2,0,KEY_SOFT1),
+       KEY(2,1,KEY_3),
+       KEY(2,2,KEY_6),
+       KEY(2,3,KEY_9),
+       KEY(2,4,KEY_SHARP),
+       KEY(2,5,KEY_2_5),
+       KEY(3,0,KEY_BACK),
+       KEY(3,1,KEY_2),
+       KEY(3,2,KEY_5),
+       KEY(3,3,KEY_8),
+       KEY(3,4,KEY_0),
+       KEY(3,5,KEY_HEADSETHOOK),
+       KEY(4,0,KEY_HOME),
+       KEY(4,1,KEY_1),
+       KEY(4,2,KEY_4),
+       KEY(4,3,KEY_7),
+       KEY(4,4,KEY_STAR),
+       KEY(4,5,KEY_POWER),
+       0
+};
+
+static int *keymap;
+
+static irqreturn_t omap_kp_interrupt(int irq, void *dev_id,
+                                    struct pt_regs *regs)
+{
+       /* disable keyboard interrupt and schedule for handling */
+       omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+       tasklet_schedule(&kp_tasklet);
+
+       return IRQ_HANDLED;
+}
+
+static void omap_kp_timer(unsigned long data)
+{
+       tasklet_schedule(&kp_tasklet);
+}
+
+static void omap_kp_scan_keypad(unsigned char *state)
+{
+       int col = 0;
+
+       /* read the keypad status */
+       omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+       for (col = 0; col < 8; col++) {
+               omap_writew(~(1 << col) & 0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+
+               if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()) {
+                       udelay(9);
+               } else {
+                       udelay(4);
+               }
+
+               state[col] = ~omap_readw(OMAP_MPUIO_BASE + OMAP_MPUIO_KBR_LATCH) & 0xff;
+       }
+       omap_writew(0x00, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+       udelay(2);
+}
+
+static inline int omap_kp_find_key(int col, int row)
+{
+       int i, key;
+
+       key = KEY(col, row, 0);
+       for (i = 0; keymap[i] != 0; i++)
+               if ((keymap[i] & 0xff000000) == key)
+                       return keymap[i] & 0x00ffffff;
+       return -1;
+}
+
+static void omap_kp_tasklet(unsigned long data)
+{
+       unsigned char new_state[8], changed, key_down = 0;
+       int col, row;
+       int spurious = 0;
+
+       /* check for any changes */
+       omap_kp_scan_keypad(new_state);
+
+       /* check for changes and print those */
+       for (col = 0; col < 8; col++) {
+               changed = new_state[col] ^ keypad_state[col];
+               key_down |= new_state[col];
+               if (changed == 0)
+                       continue;
+
+               for (row = 0; row < 8; row++) {
+                       int key;
+                       if (!(changed & (1 << row)))
+                               continue;
+#ifdef NEW_BOARD_LEARNING_MODE
+                       printk(KERN_INFO "omap-keypad: key %d-%d %s\n", col, row, (new_state[col] & (1 << row)) ? "pressed" : "released");
+#else
+                       key = omap_kp_find_key(col, row);
+                       if (key < 0) {
+                               printk(KERN_WARNING "omap-keypad: Spurious key event %d-%d\n",
+                                      col, row);
+                               /* We scan again after a couple of seconds */
+                               spurious = 1;
+                               continue;
+                       }
+
+                       input_report_key(&omap_kp_dev, key,
+                                        new_state[col] & (1 << row));
+#endif
+               }
+       }
+       memcpy(keypad_state, new_state, sizeof(keypad_state));
+
+       if (key_down) {
+                int delay = HZ / 20;
+               /* some key is pressed - keep irq disabled and use timer
+                * to poll the keypad */
+               if (spurious)
+                       delay = 2 * HZ;
+               mod_timer(&kp_timer, jiffies + delay);
+       } else {
+               /* enable interrupts */
+               omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+       }
+}
+
+static int __init omap_kp_init(void)
+{
+       int i;
+
+       printk(KERN_INFO "OMAP Keypad Driver\n");
+
+       /* Disable the interrupt for the MPUIO keyboard */
+       omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+       if (machine_is_omap_h2() || machine_is_omap_h3()) {
+               keymap = h2_keymap;
+               set_bit(EV_REP, omap_kp_dev.evbit);
+       } else if (machine_is_omap_innovator()) {
+               keymap = innovator_keymap;
+       } else if (machine_is_omap_osk()) {
+               keymap = osk_keymap;
+       } else if (machine_is_omap_perseus2()) {
+               keymap = p2_keymap;
+               keypad_irq = INT_730_MPUIO_KEYPAD;
+       } else {
+               keymap = test_keymap;
+       }
+
+       init_timer(&kp_timer);
+       kp_timer.function = omap_kp_timer;
+
+       /* get the irq and init timer*/
+       tasklet_enable(&kp_tasklet);
+       if (request_irq(keypad_irq, omap_kp_interrupt, 0,
+                       "omap-keypad", 0) < 0)
+               return -EINVAL;
+
+       /* setup input device */
+       set_bit(EV_KEY, omap_kp_dev.evbit);
+       for (i = 0; keymap[i] != 0; i++)
+               set_bit(keymap[i] & 0x00ffffff, omap_kp_dev.keybit);
+       omap_kp_dev.name = "omap-keypad";
+       input_register_device(&omap_kp_dev);
+
+       if (machine_is_omap_h2() || machine_is_omap_h3()) {
+               omap_cfg_reg(F18_1610_KBC0);
+               omap_cfg_reg(D20_1610_KBC1);
+               omap_cfg_reg(D19_1610_KBC2);
+               omap_cfg_reg(E18_1610_KBC3);
+               omap_cfg_reg(C21_1610_KBC4);
+
+               omap_cfg_reg(G18_1610_KBR0);
+               omap_cfg_reg(F19_1610_KBR1);
+               omap_cfg_reg(H14_1610_KBR2);
+               omap_cfg_reg(E20_1610_KBR3);
+               omap_cfg_reg(E19_1610_KBR4);
+               omap_cfg_reg(N19_1610_KBR5);
+
+               omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
+       } else if (machine_is_omap_perseus2()) {
+               omap_cfg_reg(E2_730_KBR0);
+               omap_cfg_reg(J7_730_KBR1);
+               omap_cfg_reg(E1_730_KBR2);
+               omap_cfg_reg(F3_730_KBR3);
+               omap_cfg_reg(D2_730_KBR4);
+
+               omap_cfg_reg(C2_730_KBC0);
+               omap_cfg_reg(D3_730_KBC1);
+               omap_cfg_reg(E4_730_KBC2);
+               omap_cfg_reg(F4_730_KBC3);
+               omap_cfg_reg(E3_730_KBC4);
+
+               omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
+       }
+
+       /* scan current status and enable interrupt */
+       omap_kp_scan_keypad(keypad_state);
+       omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+       return 0;
+}
+
+static void __exit omap_kp_exit(void)
+{
+       /* disable keypad interrupt handling */
+       tasklet_disable(&kp_tasklet);
+       omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
+       free_irq(keypad_irq, 0);
+       del_timer_sync(&kp_timer);
+
+       /* unregister everything */
+       input_unregister_device(&omap_kp_dev);
+}
+
+module_init(omap_kp_init);
+module_exit(omap_kp_exit);
+
+MODULE_AUTHOR("Timo Teräs");
+MODULE_DESCRIPTION("OMAP Keypad Driver");
+MODULE_LICENSE("GPL");
index 21d55ed4b88a69e08881a4b03f1ef9dbf20548d2..144f483fd3f4cd0c46073ee98ee1f33eb33f0d22 100644 (file)
@@ -96,3 +96,18 @@ config TOUCHSCREEN_HP600
          module will be called hp680_ts_input.
 
 endif
+config TOUCHSCREEN_OMAP
+       tristate "OMAP touchscreen input driver"
+       depends on INPUT && INPUT_TOUCHSCREEN && ARCH_OMAP
+       select OMAP_TSC2101
+       help
+         Say Y here if you have an OMAP based board with touchscreen
+         attached to it, e.g. OMAP Innovator, OSK, H2 or H3
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called omap_ts.
+
+
+
index 6842869c9a263d570b0ace2c53ace0e461cac9dc..a904d43d68ea49d4751f412001bb70b734653ba0 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Makefile for the mouse drivers.
+# Makefile for the touchscreen input drivers.
 #
 
 # Each configuration option enables a list of files.
@@ -11,3 +11,4 @@ obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
 obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)        += mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)        += hp680_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_OMAP) += omap/
diff --git a/drivers/input/touchscreen/omap/Makefile b/drivers/input/touchscreen/omap/Makefile
new file mode 100644 (file)
index 0000000..687c068
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the OMAP touchscreen input driver
+#
+
+obj-$(CONFIG_TOUCHSCREEN_OMAP) += omapts.o
+
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H2) += ts_hx.o
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += ts_hx.o
+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += ts_inn1510.o
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_OSK) += ts_osk.o
+
+omapts-objs := omap_ts.o $(objs-yy)
diff --git a/drivers/input/touchscreen/omap/ads7846.h b/drivers/input/touchscreen/omap/ads7846.h
new file mode 100644 (file)
index 0000000..ae4347a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * ads7846.h - header file for ADS7846 touchscreen controller
+ * 
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             stevel@mvista.com or source@mvista.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
+ */
+
+#ifndef __ADS7846_H
+#define __ADS7846_H
+
+// ADS7846 Control Byte bit defines
+#define ADS7846_S         (1<<7)
+#define ADS7846_ADDR_BIT  4
+#define ADS7846_ADDR_MASK (0x7<<ADS7846_ADDR_BIT)
+#define   ADS7846_MEASURE_X  (0x5<<ADS7846_ADDR_BIT)
+#define   ADS7846_MEASURE_Y  (0x1<<ADS7846_ADDR_BIT)
+#define   ADS7846_MEASURE_Z1 (0x3<<ADS7846_ADDR_BIT)
+#define   ADS7846_MEASURE_Z2 (0x4<<ADS7846_ADDR_BIT)
+#define ADS7846_8BITS     (1<<3)
+#define ADS7846_12BITS    0
+#define ADS7846_SER       (1<<2)
+#define ADS7846_DFR       0
+#define ADS7846_PWR_BIT   0
+#define   ADS7846_PD      0
+#define   ADS7846_ADC_ON  (0x1<<ADS7846_PWR_BIT)
+#define   ADS7846_REF_ON  (0x2<<ADS7846_PWR_BIT)
+#define   ADS7846_REF_ADC_ON (0x3<<ADS7846_PWR_BIT)
+
+#define MEASURE_12BIT_X \
+  (ADS7846_S | ADS7846_MEASURE_X | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
+#define MEASURE_12BIT_Y \
+  (ADS7846_S | ADS7846_MEASURE_Y | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
+#define MEASURE_12BIT_Z1 \
+  (ADS7846_S | ADS7846_MEASURE_Z1 | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
+#define MEASURE_12BIT_Z2 \
+  (ADS7846_S | ADS7846_MEASURE_Z2 | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
+
+#endif /* __ADS7846_H */
diff --git a/drivers/input/touchscreen/omap/omap_ts.c b/drivers/input/touchscreen/omap/omap_ts.c
new file mode 100644 (file)
index 0000000..269ffc7
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * input/touchscreen/omap/omap_ts.c
+ *
+ * touchscreen input device driver for various TI OMAP boards
+ * Copyright (c) 2002 MontaVista Software Inc.
+ * Copyright (c) 2004 Texas Instruments, Inc.
+ * Cleanup and modularization 2004 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * Assembled using driver code copyright the companies above.
+ *
+ * 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
+ * History:
+ * 12/12/2004    Srinath Modified and intergrated code for H2 and H3
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/device.h>
+
+#include <asm/mach-types.h>
+
+//#define DEBUG
+
+#include "omap_ts.h"
+
+#define OMAP_TS_NAME   "omap_ts"
+
+static struct ts_device *__initdata ts_devs[] = {
+#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
+       &hx_ts,
+#endif
+#ifdef CONFIG_MACH_OMAP_OSK
+       &osk_ts,
+#endif
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
+       &innovator1510_ts,
+#endif
+};
+
+static struct omap_ts_t ts_omap;
+
+static int omap_ts_read(void)
+{
+       u16 data[4] = { 0, 0, 0, 0 };
+
+       ts_omap.dev->read(data);
+
+       input_report_abs(&(ts_omap.inputdevice), ABS_X, data[0]);
+       input_report_abs(&(ts_omap.inputdevice), ABS_Y, data[1]);
+       input_report_abs(&(ts_omap.inputdevice), ABS_PRESSURE, data[2]);
+       input_sync(&(ts_omap.inputdevice));
+
+       DEBUG_TS("omap_ts_read: read x=%d,y=%d,p=%d\n", data[0], data[1],
+                data[2]);
+
+       return 0;
+}
+
+static void omap_ts_timer(unsigned long data)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ts_omap.lock, flags);
+
+       if (!ts_omap.dev->penup()) {
+               if (!ts_omap.touched) {
+                       DEBUG_TS("omap_ts_timer: pen down\n");
+                       input_report_key(&(ts_omap.inputdevice), BTN_TOUCH, 1);
+               }
+               ts_omap.touched = 1;
+               omap_ts_read();
+               ts_omap.ts_timer.expires = jiffies + HZ / 100;
+               add_timer(&(ts_omap.ts_timer));
+       } else {
+               if (ts_omap.touched) {
+                       DEBUG_TS("omap_ts_timer: pen up\n");
+                       ts_omap.touched = 0;
+                       input_report_abs(&(ts_omap.inputdevice), ABS_X, 0);
+                       input_report_abs(&(ts_omap.inputdevice), ABS_Y, 0);
+                       input_report_abs(&(ts_omap.inputdevice), ABS_PRESSURE,
+                                        0);
+                       input_sync(&(ts_omap.inputdevice));
+                       input_report_key(&(ts_omap.inputdevice), BTN_TOUCH, 0);
+               }
+               if (!ts_omap.irq_enabled) {
+                       ts_omap.irq_enabled = 1;
+                       enable_irq(ts_omap.irq);
+               }
+       }
+
+       spin_unlock_irqrestore(&ts_omap.lock, flags);
+}
+
+static irqreturn_t omap_ts_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       spin_lock(&ts_omap.lock);
+
+       if (ts_omap.irq_enabled) {
+               ts_omap.irq_enabled = 0;
+               disable_irq(irq);
+       }
+       // restart acquire
+       ts_omap.ts_timer.expires = jiffies + HZ / 100;
+       add_timer(&(ts_omap.ts_timer));
+
+       spin_unlock(&ts_omap.lock);
+
+       return IRQ_HANDLED;
+}
+
+static int __init omap_ts_probe(struct device *dev)
+{
+       int i;
+       int status = -ENODEV;
+
+       memset(&ts_omap, 0, sizeof(ts_omap));
+       spin_lock_init(&ts_omap.lock);
+
+       for (i = 0; i < ARRAY_SIZE(ts_devs); i++) {
+               if (!ts_devs[i] || !ts_devs[i]->probe)
+                       continue;
+               status = ts_devs[i]->probe(&ts_omap);
+               if (status == 0) {
+                       ts_omap.dev = ts_devs[i];
+                       break;
+               }
+       }
+
+       if (status != 0)
+               return status;
+
+       // Init acquisition timer function
+       init_timer(&ts_omap.ts_timer);
+       ts_omap.ts_timer.function = omap_ts_timer;
+
+       /* request irq */
+       if (ts_omap.irq != -1) {
+               if (request_irq(ts_omap.irq, omap_ts_handler, 0,
+                               OMAP_TS_NAME, &ts_omap)) {
+                       printk(KERN_ERR
+         "omap_ts.c: Could not allocate touchscreen IRQ!\n");
+                       ts_omap.irq = -1;
+                       return -EINVAL;
+               }
+               ts_omap.irq_enabled = 1;
+       } else {
+               printk(KERN_ERR "omap_ts.c: No touchscreen IRQ assigned!\n");
+               return -EINVAL;
+       }
+
+       init_input_dev(&(ts_omap.inputdevice));
+       ts_omap.inputdevice.name = OMAP_TS_NAME;
+       ts_omap.inputdevice.dev = dev;
+       ts_omap.inputdevice.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+       ts_omap.inputdevice.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
+       ts_omap.inputdevice.absbit[0] =
+           BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+       input_register_device(&(ts_omap.inputdevice));
+
+       ts_omap.dev->enable();
+
+       printk("OMAP touchscreen driver initialized\n");
+
+       return 0;
+}
+
+static int __exit omap_ts_remove(struct device *dev)
+{
+       ts_omap.dev->disable();
+       input_unregister_device(&ts_omap.inputdevice);
+       if (ts_omap.irq != -1)
+               free_irq(ts_omap.irq, &ts_omap);
+
+       ts_omap.dev->remove();
+
+       return 0;
+}
+
+static int omap_ts_suspend(struct device *dev, pm_message_t state)
+{
+       ts_omap.dev->disable();
+       return 0;
+}
+
+static int omap_ts_resume(struct device *dev)
+{
+       ts_omap.dev->enable();
+       return 0;
+}
+
+static void omap_ts_device_release(struct device *dev)
+{
+       /* Nothing */
+}
+
+static struct device_driver omap_ts_driver = {
+       .name           = OMAP_TS_NAME,
+       .bus            = &platform_bus_type,
+       .probe          = omap_ts_probe,
+       .remove         = __exit_p(omap_ts_remove),
+       .suspend        = omap_ts_suspend,
+       .resume         = omap_ts_resume,
+};
+
+static struct platform_device omap_ts_device = {
+       .name           = OMAP_TS_NAME,
+       .id             = -1,
+       .dev = {
+               .release        = omap_ts_device_release,
+       },
+};
+
+static int __init omap_ts_init(void)
+{
+       int ret;
+
+       ret = platform_device_register(&omap_ts_device);
+       if (ret != 0)
+               return -ENODEV;
+
+       ret = driver_register(&omap_ts_driver);
+       if (ret != 0) {
+               platform_device_unregister(&omap_ts_device);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __exit omap_ts_exit(void)
+{
+       driver_unregister(&omap_ts_driver);
+       platform_device_unregister(&omap_ts_device);
+}
+
+module_init(omap_ts_init);
+module_exit(omap_ts_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/omap/omap_ts.h b/drivers/input/touchscreen/omap/omap_ts.h
new file mode 100644 (file)
index 0000000..718b0c7
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * omap_ts.h - header file for OMAP touchscreen support
+ * 
+ * Copyright (c) 2002 MontaVista Software Inc.
+ * Copyright (c) 2004 Texas Instruments, Inc.
+ *
+ * Assembled using driver code copyright the companies above.
+ *
+ * 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
+ */
+
+#ifndef __OMAP_TS_H
+#define __OMAP_TS_H
+
+#ifdef DEBUG
+#define DEBUG_TS(fmt...)   printk(fmt)
+#else
+#define DEBUG_TS(fmt...)   do { } while (0)
+#endif
+
+struct omap_ts_t;
+
+struct ts_device {
+        int  (*probe)   (struct omap_ts_t *);
+        void (*read)    (u16 *);
+        void (*enable)  (void);
+        void (*disable) (void);
+        void (*remove)  (void);
+        int  (*penup)  (void);
+};
+
+struct omap_ts_t{
+       struct input_dev inputdevice;
+       struct timer_list ts_timer;      // Timer for triggering acquisitions
+       int touched;
+       int irq;
+       int irq_enabled;
+       struct ts_device *dev;
+       spinlock_t lock;
+};
+
+extern struct ts_device hx_ts;
+extern struct ts_device osk_ts;
+extern struct ts_device innovator1510_ts;
+
+#endif /* __OMAP_TS_H */
diff --git a/drivers/input/touchscreen/omap/ts_hx.c b/drivers/input/touchscreen/omap/ts_hx.c
new file mode 100644 (file)
index 0000000..fac78da
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * input/touchscreen/omap/ts_hx.c
+ * touchscreen support for OMAP H3 and H2  boards
+ *
+ * Copyright (c) 2002 MontaVista Software Inc.
+ * Copyright (c) 2004 Texas Instruments, Inc.
+ *
+ * Assembled using driver code copyright the companies above.
+ *
+ * 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
+ *
+ * History:
+ * 9/12/2004   Srinath Modified and integrated  H2 and H3 code
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/device.h>
+#include <asm/mach-types.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/hardware.h>
+#include <asm/hardware/tsc2101.h>
+
+#include "../drivers/ssi/omap-tsc2101.h"
+#include "omap_ts.h"
+
+#define        H2_GPIO_NUM             4
+#define        H3_GPIO_NUM             48
+
+#define OMAP_TSC2101_XRES                     500
+#define TOUCHSCREEN_DATA_REGISTERS_PAGE         0x0
+#define TOUCHSCREEN_CONTROL_REGISTERS_PAGE      0x1
+#define OMAP_TSC2101_READ_MAX             0x4
+#define TSC2101_GETSTATUS(ret)           (((ret) >> 11) & 0x1)
+#define TSC2101_MASKVAL                         0xFFF
+#define TSC2101_PRESSUREVAL(x)           ((x) << 12)
+
+static int hx_ts_penup(void);
+static int hx_ts_probe(struct omap_ts_t *ts);
+static void hx_ts_read(u16 * data);
+static void hx_ts_enable(void);
+static void hx_ts_disable(void);
+#ifdef MODULE
+static void hx_ts_remove(void);
+#endif
+
+struct ts_device hx_ts = {
+       .probe          = hx_ts_probe,
+       .read           = hx_ts_read,
+       .enable         = hx_ts_enable,
+       .disable        = hx_ts_disable,
+       .remove         = __exit_p(hx_ts_remove),
+       .penup          = hx_ts_penup,
+};
+
+static int hx_ts_penup(void)
+{
+       int ret = 0;
+       /* Read the status register */
+       ret = omap_tsc2101_read(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                               TSC2101_TS_STATUS);
+       /* Check for availability of data in status register */
+       ret = TSC2101_GETSTATUS(ret);
+       return !ret;
+
+}
+
+static int __init hx_ts_probe(struct omap_ts_t *ts)
+{
+       unsigned        gpio;
+
+       if (machine_is_omap_h2()) {
+               gpio = H2_GPIO_NUM;
+               omap_cfg_reg(P20_1610_GPIO4);
+       } else if (machine_is_omap_h3()) {
+               gpio = H3_GPIO_NUM;
+               omap_cfg_reg(W19_1610_GPIO48);
+       } else
+               return -ENODEV;
+
+       ts->irq = OMAP_GPIO_IRQ(gpio);
+       if (omap_request_gpio(gpio) != 0) {
+               printk(KERN_ERR "hX_ts_init.c: Could not reserve GPIO!\n");
+               return -EINVAL;
+       };
+
+       omap_set_gpio_direction(gpio, 1);
+       set_irq_type(ts->irq, IRQT_FALLING);
+       return 0;
+}
+
+static void hx_ts_read(u16 * values)
+{
+       s32 t, p = 0;
+       int i;
+
+       /* Read X, Y, Z1 and Z2 */
+       omap_tsc2101_reads(TOUCHSCREEN_DATA_REGISTERS_PAGE, TSC2101_TS_X,
+                          values, OMAP_TSC2101_READ_MAX);
+
+       for (i = 0; i < OMAP_TSC2101_READ_MAX; i++)
+               values[i] &= TSC2101_MASKVAL;
+
+       /* Calculate Pressure */
+       if (values[TSC2101_TS_Z1] != 0) {
+               t = ((OMAP_TSC2101_XRES * values[TSC2101_TS_X]) *
+                    (values[TSC2101_TS_Z2] - values[TSC2101_TS_Z1]));
+               p = t / (u32) (TSC2101_PRESSUREVAL(values[TSC2101_TS_Z1]));
+               if (p < 0)
+                       p = 0;
+       }
+
+       values[TSC2101_TS_Z1] = p;
+}
+
+static void hx_ts_enable(void)
+{
+       int ret = omap_tsc2101_enable();
+       if (ret) {
+               printk(KERN_ERR "FAILED TO INITIALIZE TSC CODEC\n");
+               return;
+       }
+
+       /* PINTDAV is data available only */
+       omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                          TSC2101_TS_STATUS, TSC2101_DATA_AVAILABLE);
+       /* disable buffer mode */
+       omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                          TSC2101_TS_BUFFER_CTRL, TSC2101_BUFFERMODE_DISABLE);
+       /* use internal reference, 100 usec power-up delay,
+        *        * power down between conversions, 1.25V internal reference */
+       omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                          TSC2101_TS_REF_CTRL, TSC2101_REF_POWERUP);
+       /* enable touch detection, 84usec precharge time, 32 usec sense time */
+       omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                          TSC2101_TS_CONFIG_CTRL, TSC2101_ENABLE_TOUCHDETECT);
+       /* 3 msec conversion delays  */
+       omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                          TSC2101_TS_PROG_DELAY, TSC2101_PRG_DELAY);
+       /*
+        * TSC2101-controlled conversions
+        * 12-bit samples
+        * continuous X,Y,Z1,Z2 scan mode
+        * average (mean) 4 samples per coordinate
+        * 1 MHz internal conversion clock
+        * 500 usec panel voltage stabilization delay
+        */
+       omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                          TSC2101_TS_ADC_CTRL, TSC2101_ADC_CONTROL);
+
+       return;
+
+}
+
+static void hx_ts_disable(void)
+{
+       /* stop conversions and power down */
+       omap_tsc2101_write(TOUCHSCREEN_CONTROL_REGISTERS_PAGE,
+                          TSC2101_TS_ADC_CTRL, TSC2101_ADC_POWERDOWN);
+       omap_tsc2101_disable();
+}
+
+#ifdef MODULE
+static void __exit hx_ts_remove(void)
+{
+       if (machine_is_omap_h2())
+               omap_free_gpio(H2_GPIO_NUM);
+       else if (machine_is_omap_h3())
+               omap_free_gpio(H3_GPIO_NUM);
+}
+#endif
diff --git a/drivers/input/touchscreen/omap/ts_inn1510.c b/drivers/input/touchscreen/omap/ts_inn1510.c
new file mode 100644 (file)
index 0000000..b85f003
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * ts_inn1510.c - touchscreen support for OMAP1510 Innovator board
+ * 
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             stevel@mvista.com or source@mvista.com
+ *
+ * The touchscreen hardware on the Innovator consists of an FPGA
+ * register which is bit-banged to generate SPI-like transactions
+ * to an ADS7846 touch screen controller.
+ *
+ * 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/input.h>
+#include <linux/device.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/arch/fpga.h>
+
+#include "omap_ts.h"
+#include "ads7846.h"
+
+// The Touch Screen Register on Innovator FPGA
+#define FPGA_TS_BCLK     (1<<0)
+#define FPGA_TS_BDIN     (1<<1)
+#define FPGA_TS_BCS      (1<<2)
+#define FPGA_TS_BBUSY    (1<<3)
+#define FPGA_TS_BOUT     (1<<4)
+#define FPGA_TS_BPENUP   (1<<5)
+
+#define X_PLATE_OHMS 419
+#define Y_PLATE_OHMS 486
+
+static int inn1510_ts_penup(void);
+static int inn1510_ts_probe(struct omap_ts_t *ts);
+static void inn1510_ts_read(u16 * data);
+static void inn1510_ts_enable(void);
+static void inn1510_ts_disable(void);
+#ifdef MODULE
+static void inn1510_ts_remove(void);
+#endif
+
+struct ts_device innovator1510_ts = {
+        .probe   = inn1510_ts_probe,
+        .read    = inn1510_ts_read,
+        .enable  = inn1510_ts_enable,
+        .disable = inn1510_ts_disable,
+        .remove  = __exit_p(inn1510_ts_remove),
+       .penup   = inn1510_ts_penup,
+};
+
+static inline u8 fpga_ts_read(void)
+{
+       return fpga_read(OMAP1510_FPGA_TOUCHSCREEN);
+}
+
+static inline void fpga_ts_write(u8 val)
+{
+       fpga_write(val, OMAP1510_FPGA_TOUCHSCREEN);
+}
+
+static inline void fpga_ts_set_bits(u8 mask)
+{
+       fpga_ts_write(fpga_ts_read() | mask);
+}
+
+static inline void fpga_ts_clear_bits(u8 mask)
+{
+       fpga_ts_write(fpga_ts_read() & ~mask);
+}
+
+static inline void CS_H(void)
+{
+       // EPLD inverts active low signals.
+       fpga_ts_clear_bits(FPGA_TS_BCS);
+}
+
+static inline void CS_L(void)
+{
+       fpga_ts_set_bits(FPGA_TS_BCS);
+}
+
+static inline void SCLK_L(void)
+{
+       fpga_ts_clear_bits(FPGA_TS_BCLK);
+}
+
+static inline void SCLK_H(void)
+{
+       fpga_ts_set_bits(FPGA_TS_BCLK);
+}
+
+static inline void SDI_L(void)
+{
+       fpga_ts_clear_bits(FPGA_TS_BDIN);
+}
+
+static inline void SDI_H(void)
+{
+       fpga_ts_set_bits(FPGA_TS_BDIN);
+}
+
+static inline int BUSY(void)
+{
+       return (((fpga_ts_read() & FPGA_TS_BBUSY) == 0) ? 1 : 0) ;
+}
+
+static inline u8 DOUT(void)
+{       
+       return ((fpga_ts_read() & FPGA_TS_BOUT) ? 1 : 0) ;
+}
+
+static u16 ads7846_do(u8 cmd)
+{  
+       int i;
+       u16 val=0;
+
+       SCLK_L() ;
+       SDI_L();
+       CS_L() ;        // enable the chip select
+
+       // send the command to the ADS7846
+       for (i=0; i<8; i++ ) {
+               if (cmd & 0x80)
+                       SDI_H();
+               else
+                       SDI_L();   // prepare the data on line sdi OR din
+
+               SCLK_H() ;      // clk in the data
+               cmd <<= 1 ;
+               SCLK_L() ;
+       }
+
+       SDI_L();
+       while (BUSY())
+               ;
+
+       // now read returned data
+       for (i=0 ; i<16 ; i++ ) {
+               SCLK_L() ;
+               
+               if (i < 12) {
+                       val <<= 1 ;
+                       val |= DOUT();
+               }
+               SCLK_H() ;
+       }
+
+       SCLK_L() ;
+       CS_H() ;   // disable the chip select
+
+       return val;
+}
+
+static int inn1510_ts_penup(void)
+{
+       return ((fpga_ts_read() & FPGA_TS_BPENUP) ? 0 : 1) ;
+}
+
+static int __init inn1510_ts_probe(struct omap_ts_t *ts)
+{
+       if (!cpu_is_omap15xx() || !machine_is_omap_innovator())
+               return -ENODEV;
+
+       ts->irq = OMAP1510_INT_FPGA_TS;
+       
+       return 0;
+}
+
+static void inn1510_ts_read(u16 *data)
+{
+       unsigned int Rt = 0;
+
+       data[0] = ads7846_do(MEASURE_12BIT_X);
+       data[1] = ads7846_do(MEASURE_12BIT_Y); 
+       data[2] = ads7846_do(MEASURE_12BIT_Z1); 
+       data[3] = ads7846_do(MEASURE_12BIT_Z2); 
+
+       // Calculate touch pressure resistance
+       if (data[2]) {
+               Rt = (X_PLATE_OHMS * (u32)data[0] *
+                    ((u32)data[3] - (u32)data[2])) / (u32)data[2];
+
+               Rt = (Rt + 2048) >> 12; // round up to nearest ohm
+       }
+
+       data[2] = Rt;
+}
+
+static void inn1510_ts_enable(void)
+{
+
+}
+
+static void inn1510_ts_disable(void)
+{
+
+}
+
+#ifdef MODULE
+static void __exit inn1510_ts_remove(void)
+{
+       /* Nothing to do here */
+}
+#endif
diff --git a/drivers/input/touchscreen/omap/ts_osk.c b/drivers/input/touchscreen/omap/ts_osk.c
new file mode 100644 (file)
index 0000000..45b4eb9
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * ts_osk.c - touchscreen support for OMAP OSK board
+ * 
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             stevel@mvista.com or source@mvista.com
+ *
+ * The touchscreen hardware on the OSK uses OMAP5912 uWire interface,
+ * GPIO4 (/PENIRQ) and GPIO6 (BUSY) to connect to an ADS7846 
+ * touch screen controller. GPIO6 doesn't seem to be necessary here.
+ *
+ * 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/input.h>
+#include <linux/device.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-types.h>
+
+#include "../drivers/ssi/omap-uwire.h"
+
+#include "omap_ts.h"
+#include "ads7846.h"
+
+// /PENIRQ on GPIO4 on OSK
+#define PEN_IRQ                 OMAP_GPIO_IRQ(4)
+
+// ADS7846 is on OSK uWire CS 0
+#define ADS7846_UWIRE_CS       0
+#define UWIRE_LEAVE_CS         1
+
+#define X_PLATE_OHMS 419
+#define Y_PLATE_OHMS 486
+
+static int osk_ts_penup(void);
+static int osk_ts_probe(struct omap_ts_t *ts);
+static void osk_ts_read(u16 * data);
+static void osk_ts_enable(void);
+static void osk_ts_disable(void);
+#ifdef MODULE
+static void osk_ts_remove(void);
+#endif
+
+struct ts_device osk_ts = {
+        .probe   = osk_ts_probe,
+        .read    = osk_ts_read,
+        .enable  = osk_ts_enable,
+        .disable = osk_ts_disable,
+        .remove  = __exit_p(osk_ts_remove),
+       .penup   = osk_ts_penup,
+};
+
+static u16 ads7846_do(u8 cmd)
+{
+       u16 val = 0;
+       
+       // send the command to the ADS7846, leave CS active after this
+       omap_uwire_data_transfer(ADS7846_UWIRE_CS, cmd, 8, 0, NULL, UWIRE_LEAVE_CS);
+
+       // now read returned data
+        omap_uwire_data_transfer(ADS7846_UWIRE_CS, 0, 0, 16, &val, !UWIRE_LEAVE_CS);
+       
+       return val;
+}
+
+static int osk_ts_penup(void)
+{
+       return (omap_get_gpio_datain(4));
+}
+
+static int  __init osk_ts_probe(struct omap_ts_t *ts)
+{
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+       if (!machine_is_omap_osk())
+               return -ENODEV;
+
+        /* Configure GPIO4 (pin M17 ZDY) as /PENIRQ interrupt input */
+        omap_cfg_reg(P20_1610_GPIO4);
+       omap_request_gpio(4);
+       omap_set_gpio_direction(4, 1);
+       set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
+
+       ts->irq = PEN_IRQ;
+
+       /* Configure uWire interface. ADS7846 is on CS0 */
+       omap_uwire_configure_mode(ADS7846_UWIRE_CS, UWIRE_READ_RISING_EDGE |
+                                                   UWIRE_WRITE_RISING_EDGE |
+                                                   UWIRE_CS_ACTIVE_LOW |
+                                                   UWIRE_FREQ_DIV_2);
+
+       /* FIXME verify there's really a Mistral board:
+        * see if the AD7846 chip responds.
+        */
+
+       /* NOTE:  no VREF; must ignore the temp, VBAT, and AUX sensors */
+       return 0;
+#else
+       return -ENODEV;
+#endif
+}
+
+static void osk_ts_read(u16 *data)
+{
+       unsigned int Rt = 0;
+
+       data[0] = ads7846_do(MEASURE_12BIT_X);
+       data[1] = ads7846_do(MEASURE_12BIT_Y); 
+       data[2] = ads7846_do(MEASURE_12BIT_Z1); 
+       data[3] = ads7846_do(MEASURE_12BIT_Z2); 
+
+       // Calculate touch pressure resistance
+       if (data[2]) {
+               Rt = (X_PLATE_OHMS * (u32)data[0] *
+                    ((u32)data[3] - (u32)data[2])) / (u32)data[2];
+
+               Rt = (Rt + 2048) >> 12; // round up to nearest ohm
+       }
+
+       /* 
+        * Raw OSK touchscreen data values are between ~4000 and
+        * ~60000. This seems to be to large for calibration 
+        * systems (e.g. tslib). Make the values smaller.
+        */
+       data[0] = data[0] >> 4;
+       data[1] = data[1] >> 4;
+
+       data[2] = Rt;
+}
+
+static void osk_ts_enable(void)
+{
+
+}
+
+static void osk_ts_disable(void)
+{
+
+}
+
+#ifdef MODULE
+static void __exit osk_ts_remove(void)
+{
+       omap_free_gpio(4);
+}
+#endif
index 199b01188858325e169adb8f9a3e5caa6fc509bf..6777e96330a859c2eb8ba9bc1e8fed7251a8fc04 100644 (file)
@@ -333,4 +333,10 @@ config VIDEO_M32R_AR_M64278
          Say Y here to use the Renesas M64278E-800 camera module,
          which supports VGA(640x480 pixcels) size of images.
 
+config VIDEO_OMAP_CAMERA
+       tristate "OMAP Video for Linux camera driver"
+       depends on VIDEO_DEV && ARCH_OMAP16XX
+       select VIDEO_BUF
+
+
 endmenu
index 3ac465992400b12ab438ffca5306d59c73fbca65..e054ce25912535ab05627f3cc71497228a2416c3 100644 (file)
@@ -54,5 +54,6 @@ obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
 
 obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
+obj-$(CONFIG_VIDEO_OMAP_CAMERA) += omap/
 
 EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
diff --git a/drivers/media/video/omap/Makefile b/drivers/media/video/omap/Makefile
new file mode 100644 (file)
index 0000000..1f6476a
--- /dev/null
@@ -0,0 +1,7 @@
+# Makefile for camera driver for H2/H3
+
+omapCamera-objs :=  camera_core.o omap16xxcam.o sensor_ov9640.o  
+
+obj-y += omapCamera.o
+
+EXTRA_CFLAGS = -I$(src)/..
diff --git a/drivers/media/video/omap/camera_core.c b/drivers/media/video/omap/camera_core.c
new file mode 100644 (file)
index 0000000..077d2b0
--- /dev/null
@@ -0,0 +1,1189 @@
+/*
+ * drivers/media/video/omap/camera_core.c
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc. 
+ *
+ * Video-for-Linux (Version 2) camera capture driver for
+ * the OMAP H2 and H3 camera controller.
+ *
+ * Adapted from omap24xx driver written by Andy Lowe (source@mvista.com)
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * 
+ * This package 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. 
+ * 
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
+ *
+ * History:
+ *   27/03/05   Vladimir Barinov - Added support for power management
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/videodev.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+
+#include "sensor_if.h"
+#include "camera_hw_if.h"
+#include "camera_core.h"
+struct camera_device *camera_dev;
+extern struct camera_sensor camera_sensor_if;
+extern struct camera_hardware camera_hardware_if;
+static void camera_core_sgdma_process(struct camera_device *cam);
+
+/* module parameters */
+static int video_nr = -1;      /* video device minor (-1 ==> auto assign) */
+
+/* Maximum amount of memory to use for capture buffers.
+ * Default is 4800KB, enough to double-buffer SXGA.
+ */
+static int capture_mem = 1280*960*2*2;
+
+/*Size of video overlay framebuffer. This determines the maximum image size
+ *that can be previewed. Default is 600KB, enough for sxga.
+ */
+static int overlay_mem = 640*480*2;
+
+/* DMA completion routine for the scatter-gather DMA fragments. */
+/* This function is called when a scatter DMA fragment is completed */
+static void
+camera_core_callback_sgdma(void *arg1, void *arg2)
+{
+       struct camera_device *cam = (struct camera_device *)arg1;
+       int sgslot = (int)arg2;
+
+       struct sgdma_state *sgdma;
+
+       spin_lock(&cam->sg_lock);
+       sgdma = cam->sgdma + sgslot;
+       if (!sgdma->queued_sglist)
+       {
+               spin_unlock(&cam->sg_lock);
+               printk(KERN_ERR CAM_NAME ": SGDMA completed when none queued\n");
+               return;
+       }
+       if (!--sgdma->queued_sglist) {
+               /* queue for this sglist is empty so check whether transfer
+               ** of the frame has been completed */
+               if (sgdma->next_sglist == sgdma->sglen) {
+                       dma_callback_t callback = sgdma->callback;
+                       void *arg = sgdma->arg;
+                       /* all done with this sglist */
+                       cam->free_sgdma++;
+                       if (callback) {
+                               spin_unlock(&cam->sg_lock);
+                               (*callback)(cam, arg);
+                               camera_core_sgdma_process(cam);
+                               return;
+                       }
+               }
+       }
+       spin_unlock(&cam->sg_lock);
+       camera_core_sgdma_process(cam);
+
+       return;
+}
+
+static void
+camera_core_sgdma_init(struct camera_device *cam)
+{
+       int sg;
+
+       /* Initialize the underlying camera DMA */
+       cam->cam_hardware->init_dma(cam->hardware_data);
+       spin_lock_init(&cam->sg_lock);
+       
+       cam->free_sgdma = NUM_SG_DMA;
+       cam->next_sgdma = 0;
+       for (sg = 0; sg < NUM_SG_DMA; sg++) {
+               cam->sgdma[sg].sglen = 0;
+               cam->sgdma[sg].next_sglist = 0;
+               cam->sgdma[sg].queued_sglist = 0;
+               cam->sgdma[sg].csr = 0;
+               cam->sgdma[sg].callback = NULL;
+               cam->sgdma[sg].arg = NULL;
+       }
+}
+
+/*
+ * Process the scatter-gather DMA queue by starting queued transfers
+ * This function is called to program the dma to start the transfer of an image.
+ */
+static void
+camera_core_sgdma_process(struct camera_device *cam)
+{
+       unsigned long irqflags;
+       int queued_sgdma, sgslot;
+       struct sgdma_state *sgdma;
+       const struct scatterlist *sglist;
+       
+       spin_lock_irqsave(&cam->sg_lock, irqflags);
+       if (1 == cam->in_use) {
+               spin_unlock_irqrestore(&cam->sg_lock, irqflags);
+               return;
+       }
+       cam->in_use = 1;
+       spin_unlock_irqrestore(&cam->sg_lock, irqflags);
+
+       queued_sgdma = NUM_SG_DMA - cam->free_sgdma;
+       sgslot = (cam->next_sgdma + cam->free_sgdma) % (NUM_SG_DMA);
+       while (queued_sgdma > 0) {
+               sgdma = cam->sgdma + sgslot;
+               while (sgdma->next_sglist < sgdma->sglen) {
+                       sglist = sgdma->sglist + sgdma->next_sglist;
+                       if (cam->cam_hardware->start_dma(sgdma, camera_core_callback_sgdma,
+                               (void *)cam, (void *)sgslot, cam->hardware_data)) {
+                                       /* dma start failed */
+                                       cam->in_use = 0;
+                                       return;
+                       }
+                       else {
+                               /* dma start successful */
+                               sgdma->next_sglist ++;
+                               sgdma->queued_sglist ++;
+                       }
+               }
+               queued_sgdma-- ;
+               sgslot = (sgslot + 1) % (NUM_SG_DMA);
+       }
+
+       cam->in_use = 0;
+}
+
+/* Queue a scatter-gather DMA transfer from the camera to memory.
+ * Returns zero if the transfer was successfully queued, or
+ * non-zero if all of the scatter-gather slots are already in use.
+ */
+static int
+camera_core_sgdma_queue(struct camera_device *cam,
+        const struct scatterlist *sglist, int sglen, dma_callback_t callback,
+        void *arg)
+{
+       unsigned long irqflags;
+       struct sgdma_state *sgdma;
+
+       if ((sglen < 0) || ((sglen > 0) & !sglist))
+               return -EINVAL;
+
+       spin_lock_irqsave(&cam->sg_lock, irqflags);
+
+       if (!cam->free_sgdma) {
+               spin_unlock_irqrestore(&cam->sg_lock, irqflags);
+               return -EBUSY;
+       }
+
+       sgdma = cam->sgdma + cam->next_sgdma;
+
+       sgdma->sglist = sglist;
+       sgdma->sglen = sglen;
+       sgdma->next_sglist = 0;
+       sgdma->queued_sglist = 0;
+       sgdma->csr = 0;
+       sgdma->callback = callback;
+       sgdma->arg = arg;
+
+       cam->next_sgdma = (cam->next_sgdma + 1) % (NUM_SG_DMA); 
+       cam->free_sgdma--;
+
+       spin_unlock_irqrestore(&cam->sg_lock, irqflags);
+
+       camera_core_sgdma_process(cam);
+
+       return 0;
+}
+
+
+/* -------------------overlay routines ------------------------------*/
+/* callback routine for overlay DMA completion. We just start another DMA
+ * transfer unless overlay has been turned off
+ */
+
+static void
+camera_core_overlay_callback(void *arg1, void *arg)
+{
+       struct camera_device *cam = (struct camera_device *)arg1;
+       int err;
+       unsigned long irqflags;
+       int i, j;
+       int count, index;
+       unsigned char *fb_buf = phys_to_virt((unsigned long)camera_dev->fbuf.base);
+
+       spin_lock_irqsave(&cam->overlay_lock, irqflags);
+
+       if (!cam->previewing || cam->overlay_cnt == 0) {
+               spin_unlock_irqrestore(&cam->overlay_lock, irqflags);
+               return;
+       }
+
+       --cam->overlay_cnt;
+       sg_dma_address(&cam->overlay_sglist) = cam->overlay_base_phys;
+       sg_dma_len(&cam->overlay_sglist) = cam->pix.sizeimage;
+
+       count = 0;
+       j = ((cam->pix.width - 1) * cam->fbuf.fmt.bytesperline);
+       for (i = 0 ; i < cam->pix.sizeimage; i += cam->pix.bytesperline) {
+               for (index = 0; index < cam->pix.bytesperline; index++) {
+                       fb_buf[j] = *(((unsigned char *) cam->overlay_base) +
+                                                                i + index);
+                       index++;
+                       fb_buf[j + 1] = *(((unsigned char *) cam->overlay_base) + i + index);
+                       j = j - cam->fbuf.fmt.bytesperline;
+               }
+               count += 2;
+               j = ((cam->pix.width - 1) * cam->fbuf.fmt.bytesperline) + count;
+       }
+
+       while (cam->overlay_cnt < 2) {
+               err = camera_core_sgdma_queue(cam, &cam->overlay_sglist, 1,
+                       camera_core_overlay_callback, NULL);
+               if (err)
+                       break;
+               ++cam->overlay_cnt;
+       }
+
+       spin_unlock_irqrestore(&cam->overlay_lock, irqflags);
+
+}
+
+static void
+camera_core_start_overlay(struct camera_device *cam)
+{
+       int err;
+       unsigned long irqflags;
+
+       if (!cam->previewing) 
+               return;
+
+       spin_lock_irqsave(&cam->overlay_lock, irqflags);
+
+       sg_dma_address(&cam->overlay_sglist) = cam->overlay_base_phys;
+       sg_dma_len(&cam->overlay_sglist)= cam->pix.sizeimage;
+       while (cam->overlay_cnt < 2) {
+               err = camera_core_sgdma_queue(cam, &cam->overlay_sglist, 1,
+                               camera_core_overlay_callback, NULL);
+               if (err)
+                       break;
+               ++cam->overlay_cnt;
+       }
+
+       spin_unlock_irqrestore(&cam->overlay_lock, irqflags);
+}
+
+/* ------------------ videobuf_queue_ops ---------------------------------------- */
+
+/* This routine is called from interrupt context when a scatter-gather DMA
+ * transfer of a videobuf_buffer completes.
+ */
+static void
+camera_core_vbq_complete(void *arg1, void *arg)
+{
+       struct camera_device *cam = (struct camera_device *)arg1;
+       struct videobuf_buffer *vb = (struct videobuf_buffer *)arg;
+
+       spin_lock(&cam->vbq_lock);
+
+       do_gettimeofday(&vb->ts);
+       vb->field_count = cam->field_count;
+       cam->field_count += 2;
+       vb->state = STATE_DONE;
+
+       wake_up(&vb->done);
+       
+       spin_unlock(&cam->vbq_lock);
+}
+
+static void
+camera_core_vbq_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       videobuf_waiton(vb, 0, 0);
+       videobuf_dma_pci_unmap(NULL, &vb->dma);
+       videobuf_dma_free(&vb->dma);
+
+       vb->state = STATE_NEEDS_INIT;
+}
+
+/* Limit the number of available kernel image capture buffers based on the
+ * number requested, the currently selected image size, and the maximum
+ * amount of memory permitted for kernel capture buffers.
+ */
+static int
+camera_core_vbq_setup(struct videobuf_queue *q, unsigned int *cnt, unsigned int *size)
+{
+       struct camera_device *cam = q->priv_data;
+
+       if (*cnt <= 0)
+               *cnt = VIDEO_MAX_FRAME; /* supply a default number of buffers */
+
+       if (*cnt > VIDEO_MAX_FRAME)
+               *cnt = VIDEO_MAX_FRAME;
+
+       spin_lock(&cam->img_lock);
+       *size = cam->pix.sizeimage;
+       spin_unlock(&cam->img_lock);
+
+       while (*size * *cnt > capture_mem)
+               (*cnt)--;
+
+       return 0;
+}
+
+static int
+camera_core_vbq_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+        enum v4l2_field field)
+{
+       struct camera_device *cam = q->priv_data;
+       int err = 0;
+
+       spin_lock(&cam->img_lock);
+       if (cam->pix.sizeimage > vb->bsize) {
+               spin_unlock(&cam->img_lock);
+               return -EINVAL;
+       }
+       vb->size = cam->pix.sizeimage; 
+       vb->width = cam->pix.width;
+       vb->height = cam->pix.height;
+       vb->field = field;
+       spin_unlock(&cam->img_lock);
+
+       if (vb->state == STATE_NEEDS_INIT)
+               err = videobuf_iolock(NULL, vb, NULL);
+
+       if (!err)
+               vb->state = STATE_PREPARED;
+       else
+               camera_core_vbq_release (q, vb);
+
+       return err;
+}
+
+static void
+camera_core_vbq_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct camera_device *cam = q->priv_data;
+       enum videobuf_state state = vb->state;
+       int err;
+
+       vb->state = STATE_QUEUED;
+       err = camera_core_sgdma_queue(cam, vb->dma.sglist, vb->dma.sglen,
+                camera_core_vbq_complete, vb);
+       if (err) {
+               /* Oops.  We're not supposed to get any errors here.  The only
+               * way we could get an error is if we ran out of scatter-gather
+               * DMA slots, but we are supposed to have at least as many
+               * scatter-gather DMA slots as video buffers so that can't
+               * happen.
+               */
+               printk(KERN_DEBUG CAM_NAME
+                       ": Failed to queue a video buffer for SGDMA\n");
+               vb->state = state;
+       }
+}
+
+/* ------------------ videobuf_queue_ops ---------------------------------------- */
+
+static int
+camera_core_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
+                    void *arg)
+{
+       struct camera_fh *fh  = file->private_data;
+       struct camera_device *cam = fh->cam;
+       int err;
+
+       switch (cmd) {
+               case VIDIOC_ENUMINPUT:
+               {
+                       /* default handler assumes 1 video input (the camera) */
+                       struct v4l2_input *input = (struct v4l2_input *)arg;
+                       int index = input->index;
+
+                       memset(input, 0, sizeof(*input));
+                       input->index = index;
+
+                       if (index > 0)
+                               return -EINVAL;
+
+                       strlcpy(input->name, "camera", sizeof(input->name));
+                       input->type = V4L2_INPUT_TYPE_CAMERA;
+
+                       return 0;
+               }
+
+               case VIDIOC_G_INPUT:
+               {
+                       unsigned int *input = arg;
+                       *input = 0;
+
+                       return 0;
+               }
+
+               case VIDIOC_S_INPUT:
+               {
+                       unsigned int *input = arg;
+
+                       if (*input > 0)
+                               return -EINVAL;
+
+                       return 0;
+               }
+
+               case VIDIOC_ENUM_FMT:
+               {
+                       struct v4l2_fmtdesc *fmt = arg;
+                       return cam->cam_sensor->enum_pixformat(fmt, cam->sensor_data);
+               }       
+
+               case VIDIOC_TRY_FMT:
+               {
+                       struct v4l2_format *fmt = arg;
+                       return cam->cam_sensor->try_format(&fmt->fmt.pix, cam->sensor_data);
+
+               }
+
+               case VIDIOC_G_FMT:
+               {
+                       struct v4l2_format *fmt = arg;
+
+                       /* get the current format */
+                       memset(&fmt->fmt.pix, 0, sizeof (fmt->fmt.pix));
+                       fmt->fmt.pix = cam->pix;
+                       
+                       return 0;
+               }
+
+               case VIDIOC_S_FMT:
+               {
+                       struct v4l2_format *fmt = arg;
+                       unsigned int temp_sizeimage = 0;
+
+                       temp_sizeimage = cam->pix.sizeimage;
+                       cam->cam_sensor->try_format(&fmt->fmt.pix, cam->sensor_data);
+                       cam->pix = fmt->fmt.pix;
+
+                       cam->xclk = cam->cam_sensor->calc_xclk(&cam->pix,
+                               &cam->nominal_timeperframe, cam->sensor_data);
+                       cam->cparm.timeperframe = cam->nominal_timeperframe;
+                       cam->xclk = cam->cam_hardware->set_xclk(cam->xclk, cam->hardware_data);
+                       return cam->cam_sensor->configure(&cam->pix, cam->xclk, 
+                                               &cam->cparm.timeperframe, cam->sensor_data);
+               }
+
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *qc = arg;
+                       return cam->cam_sensor->query_control(qc, cam->sensor_data);
+               }
+
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *vc = arg;
+                       return cam->cam_sensor->get_control(vc, cam->sensor_data);
+               }
+
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *vc = arg;
+                       return cam->cam_sensor->set_control(vc, cam->sensor_data);
+               }
+               
+               case VIDIOC_QUERYCAP:
+               {
+                       struct v4l2_capability *cap = 
+                               (struct v4l2_capability *) arg;
+
+                       memset(cap, 0, sizeof(*cap));
+                       strlcpy(cap->driver, CAM_NAME, sizeof(cap->driver));
+                       strlcpy(cap->card, cam->vfd->name, sizeof(cap->card));
+                       cap->bus_info[0] = '\0';
+                       cap->version = KERNEL_VERSION(0, 0, 0);
+                       cap->capabilities =
+                               V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_VIDEO_OVERLAY |
+                               V4L2_CAP_READWRITE | 
+                               V4L2_CAP_STREAMING;
+                       return 0;
+               }
+
+               case VIDIOC_G_FBUF: /* Get the frame buffer parameters */
+               {
+                       struct v4l2_framebuffer *fbuf =
+                               (struct v4l2_framebuffer *) arg;
+
+                       spin_lock(&cam->img_lock);
+                       *fbuf = cam->fbuf;
+                       spin_unlock(&cam->img_lock);
+                       return 0;
+               }
+
+               case VIDIOC_S_FBUF: /* set the frame buffer parameters */
+               {
+                       struct v4l2_framebuffer *fbuf =
+                               (struct v4l2_framebuffer *) arg;
+
+                       spin_lock(&cam->img_lock);
+                       if (cam->previewing) {
+                               spin_unlock(&cam->img_lock);
+                               return -EBUSY;
+                       }
+                       cam->fbuf.base = fbuf->base;
+                       cam->fbuf.fmt = fbuf->fmt;      
+                       
+                       spin_unlock(&cam->img_lock);
+                       return 0;
+               }
+
+               case VIDIOC_OVERLAY:
+               {
+                       int enable = *((int *) arg);
+
+                       /* 
+                        * check whether the capture format and 
+                        ** the display format matches 
+                        * return failure if they are different
+                        */
+                       if (cam->pix.pixelformat != cam->fbuf.fmt.pixelformat)
+                       {
+                               return -EINVAL;
+                       }
+
+                       /* If the camera image size is greater 
+                       ** than LCD size return failure */
+                       if ((cam->pix.width > cam->fbuf.fmt.height) || 
+                               (cam->pix.height > cam->fbuf.fmt.width))
+                       {
+                               return -EINVAL;
+                       }
+                       
+                       if (!cam->previewing && enable)
+                       {
+                               cam->previewing = fh;
+                               cam->overlay_cnt = 0;
+                               camera_core_start_overlay(cam);
+                       }
+                       else if (!enable)
+                       {
+                               cam->previewing = NULL;
+                       }
+       
+                       return 0;
+               }
+
+               case VIDIOC_REQBUFS:
+                       return videobuf_reqbufs(&fh->vbq, arg);
+
+               case VIDIOC_QUERYBUF:
+                       return videobuf_querybuf(&fh->vbq, arg);
+
+               case VIDIOC_QBUF:
+                       return videobuf_qbuf(&fh->vbq, arg);
+
+               case VIDIOC_DQBUF:
+                       return videobuf_dqbuf(&fh->vbq, arg,
+          file->f_flags & O_NONBLOCK);
+
+               case VIDIOC_STREAMON:
+               {
+                       spin_lock(&cam->img_lock);
+
+                       if (cam->streaming || cam->reading) {
+                               spin_unlock(&cam->img_lock);
+                               return -EBUSY;
+                       }
+                       else {
+                               cam->streaming = fh;
+                               /* FIXME: start camera interface */
+                       }
+
+                       spin_unlock(&cam->img_lock);
+
+                       return videobuf_streamon(&fh->vbq);
+               }
+               case VIDIOC_STREAMOFF:
+               {
+                       err = videobuf_streamoff(&fh->vbq);
+                       if (err < 0)
+                               return err;
+
+                       spin_lock(&cam->img_lock);
+                       if (cam->streaming == fh) {
+                               cam->streaming = NULL;
+                               /* FIXME: stop camera interface */
+                       }
+                       spin_unlock(&cam->img_lock);
+                       return 0;
+               }
+               case VIDIOC_ENUMSTD:
+               case VIDIOC_G_STD:
+               case VIDIOC_S_STD:
+               case VIDIOC_QUERYSTD:
+               {
+                       /* Digital cameras don't have an analog video standard, 
+                        * so we don't need to implement these ioctls.
+                        */
+                        return -EINVAL;
+               }
+               case VIDIOC_G_AUDIO:
+               case VIDIOC_S_AUDIO:
+               case VIDIOC_G_AUDOUT:
+               case VIDIOC_S_AUDOUT:
+               {
+                       /* we don't have any audio inputs or outputs */
+                       return -EINVAL;
+               }
+
+               case VIDIOC_G_JPEGCOMP:
+               case VIDIOC_S_JPEGCOMP:
+               {
+                       /* JPEG compression is not supported */
+                       return -EINVAL;
+               }
+
+               case VIDIOC_G_TUNER:
+               case VIDIOC_S_TUNER:
+               case VIDIOC_G_MODULATOR:
+               case VIDIOC_S_MODULATOR:
+               case VIDIOC_G_FREQUENCY:
+               case VIDIOC_S_FREQUENCY:
+               {
+                       /* we don't have a tuner or modulator */
+                       return -EINVAL;
+               }
+
+               case VIDIOC_ENUMOUTPUT:
+               case VIDIOC_G_OUTPUT:
+               case VIDIOC_S_OUTPUT:
+               {
+                       /* we don't have any video outputs */
+                       return -EINVAL;
+               }
+
+               default:
+               {
+                       /* unrecognized ioctl */
+                       return -ENOIOCTLCMD;
+               }
+       }
+       return 0;
+}
+
+/*
+ *  file operations
+ */
+
+static unsigned
+int camera_core_poll(struct file *file, struct poll_table_struct *wait)
+{
+       return -EINVAL;
+}
+
+/* ------------------------------------------------------------ */
+/* callback routine for read DMA completion. We just start another DMA
+ * transfer unless overlay has been turned off
+ */
+static void
+camera_core_capture_callback(void *arg1, void *arg)
+{
+       struct camera_device *cam = (struct camera_device *)arg1;
+       int err;
+       unsigned long irqflags;
+       static int done = 0;
+
+       spin_lock_irqsave(&cam->capture_lock, irqflags);
+       if (!cam->reading)
+       {
+               done = 0;
+               cam->capture_started = 0;
+               spin_unlock_irqrestore(&cam->capture_lock, irqflags);
+               return;
+       }
+
+       if (done < 14) {
+               ++done;
+               sg_dma_address(&cam->capture_sglist) = cam->capture_base_phys;
+               sg_dma_len(&cam->capture_sglist) = cam->pix.sizeimage;
+               err = camera_core_sgdma_queue(cam, &cam->capture_sglist, 1,
+                       camera_core_capture_callback, NULL);            
+       } else {
+               cam->capture_completed = 1;
+               if (cam->reading)
+               {
+                       /* Wake up any process which are waiting for the 
+                       ** DMA to complete */
+                       wake_up_interruptible(&camera_dev->new_video_frame);
+                       sg_dma_address(&cam->capture_sglist) = cam->capture_base_phys;
+                       sg_dma_len(&cam->capture_sglist) = cam->pix.sizeimage;
+                       err = camera_core_sgdma_queue(cam, &cam->capture_sglist, 1,
+                               camera_core_capture_callback, NULL);
+               }
+       }
+
+       spin_unlock_irqrestore(&cam->capture_lock, irqflags);
+}
+
+static ssize_t
+camera_core_read(struct file *file, char *data, size_t count, loff_t *ppos)
+{
+       struct camera_fh *fh = file->private_data;
+       struct camera_device *cam = fh->cam;
+       int err;
+       unsigned long irqflags;
+       long timeout;
+#if 0  /* use video_buf to do capture */
+       int i;
+       for (i = 0; i < 14; i++)
+               videobuf_read_one(file, &fh->vbq, data, count, ppos);
+       i = videobuf_read_one(file, &fh->vbq, data, count, ppos);
+       return i;
+#endif
+       
+       if (!cam->capture_base) {
+               cam->capture_base = (unsigned long)dma_alloc_coherent(NULL,
+                               cam->pix.sizeimage,
+                               (dma_addr_t *) &cam->capture_base_phys,
+                               GFP_KERNEL | GFP_DMA);
+       }
+       if (!cam->capture_base) {
+               printk(KERN_ERR CAM_NAME
+                       ": cannot allocate capture buffer\n");
+               return 0;
+       }
+
+       spin_lock_irqsave(&cam->capture_lock, irqflags);
+       cam->reading = fh;
+       cam->capture_started = 1;
+       sg_dma_address(&cam->capture_sglist) = cam->capture_base_phys;
+       sg_dma_len(&cam->capture_sglist)= cam->pix.sizeimage;
+       spin_unlock_irqrestore(&cam->capture_lock, irqflags);
+
+       err = camera_core_sgdma_queue(cam, &cam->capture_sglist, 1,
+                       camera_core_capture_callback, NULL);
+
+       /* Wait till DMA is completed */
+       timeout = HZ * 10;
+       cam->capture_completed = 0;
+       while (cam->capture_completed == 0) {
+               timeout = interruptible_sleep_on_timeout 
+                               (&cam->new_video_frame, timeout);
+               if (timeout == 0) {
+                       printk(KERN_ERR CAM_NAME ": timeout waiting video frame\n");    
+                       return -EIO; /* time out */
+               }
+       }
+       /* copy the data to the user buffer */
+       err = copy_to_user(data, (void *)cam->capture_base, cam->pix.sizeimage);
+       return (cam->pix.sizeimage - err);
+       
+}
+
+static int
+camera_core_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct camera_fh *fh = file->private_data;
+
+       return videobuf_mmap_mapper(&fh->vbq, vma);
+}
+
+static int
+camera_core_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
+                 unsigned long arg)
+{
+
+       return video_usercopy(inode, file, cmd, arg, camera_core_do_ioctl);
+}
+
+static int
+camera_core_release(struct inode *inode, struct file *file)
+{
+       struct camera_fh *fh = file->private_data;
+       struct camera_device *cam = fh->cam;
+       
+       file->private_data = NULL;
+       kfree(fh);
+
+       spin_lock(&cam->img_lock);
+       if (cam->previewing == fh) {
+               cam->previewing = NULL;
+       }
+       if (cam->streaming == fh) {
+               cam->streaming = NULL;
+       }
+       if (cam->reading == fh) {
+               cam->reading = NULL;
+       }
+       spin_unlock(&cam->img_lock);
+
+       camera_dev->cam_hardware->finish_dma(cam->hardware_data);
+
+       if (cam->capture_base) {
+               dma_free_coherent(NULL, cam->pix.sizeimage, 
+                                       (void *)cam->capture_base, 
+                                       cam->capture_base_phys);
+               cam->capture_base = 0;
+               cam->capture_base_phys = 0;
+       }
+       if (fh->vbq.read_buf) {
+               camera_core_vbq_release(&fh->vbq, fh->vbq.read_buf);
+               kfree(fh->vbq.read_buf);
+       }
+
+       cam->cam_hardware->close(cam->hardware_data);
+       cam->active = 0;
+       return 0;
+}
+
+static int
+camera_core_open(struct inode *inode, struct file *file)
+{
+       int minor = iminor(inode);
+       struct camera_device *cam = camera_dev;
+       struct camera_fh *fh;
+
+       if (!cam || !cam->vfd || (cam->vfd->minor != minor))
+               return -ENODEV;
+
+       /* allocate per-filehandle data */
+       fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+       file->private_data = fh;
+       fh->cam = cam;
+       fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       spin_lock(&cam->img_lock);
+       if (cam->active == 1) {
+               printk (KERN_ERR CAM_NAME ": Camera device Active\n");
+               spin_unlock(&cam->img_lock);
+               return -EPERM;
+       }
+       cam->active = 1;
+       spin_unlock(&cam->img_lock);
+
+       videobuf_queue_init(&fh->vbq, &cam->vbq_ops, NULL, &cam->vbq_lock,
+               fh->type, V4L2_FIELD_NONE, sizeof(struct videobuf_buffer), fh);
+
+       cam->capture_completed = 0;
+       cam->capture_started = 0;
+
+       if (cam->cam_hardware->open(cam->hardware_data))
+       {
+               printk (KERN_ERR CAM_NAME ": Camera IF configuration failed\n");
+               cam->active = 0;
+               return -ENODEV;
+       }
+       
+       cam->xclk = cam->cam_hardware->set_xclk(cam->xclk, cam->hardware_data);
+       /* program the sensor for the capture format and rate */
+       if (cam->cam_sensor->configure(&cam->pix, cam->xclk, 
+                               &cam->cparm.timeperframe, cam->sensor_data))
+       {
+               printk (KERN_ERR CAM_NAME ": Camera sensor configuration failed\n");
+               cam->cam_hardware->close(cam->hardware_data);
+               cam->active = 0;
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int camera_core_suspend(struct device *dev, pm_message_t state)
+{
+       struct camera_device *cam = dev_get_drvdata(dev);
+       int ret = 0;
+
+       spin_lock(&cam->img_lock);
+       if (cam->active) {
+               cam->cam_hardware->close(cam->hardware_data);
+       }
+       cam->cam_sensor->power_off(cam->sensor_data);
+       spin_unlock(&cam->img_lock);
+       return ret;
+}
+
+static int camera_core_resume(struct device *dev)
+{
+       struct camera_device *cam = dev_get_drvdata(dev);
+       int ret = 0;
+
+       spin_lock(&cam->img_lock);
+       cam->cam_sensor->power_on(cam->sensor_data);
+       if (cam->active) {
+               cam->capture_completed = 1;
+               cam->cam_hardware->open(cam->hardware_data);
+               cam->cam_hardware->set_xclk(cam->xclk, cam->hardware_data);
+
+               cam->cam_sensor->configure(&cam->pix, cam->xclk,
+                                          &cam->cparm.timeperframe,
+                                          cam->sensor_data);
+               camera_core_sgdma_process(cam);
+       }
+       spin_unlock(&cam->img_lock);
+
+       return ret;
+}
+#endif /* CONFIG_PM */
+
+static struct file_operations camera_core_fops = 
+{
+       .owner                  = THIS_MODULE,
+       .llseek                 = no_llseek,
+       .read                   = camera_core_read,
+       .poll                   = camera_core_poll,
+       .ioctl                  = camera_core_ioctl,
+       .mmap                   = camera_core_mmap,
+       .open                   = camera_core_open,
+       .release                = camera_core_release,
+};
+
+static struct device_driver camera_core_driver = {
+       .name                   = CAM_NAME,
+       .bus                    = &platform_bus_type,
+       .probe                  = NULL,
+       .remove                 = NULL,
+#ifdef CONFIG_PM
+       .suspend                = camera_core_suspend,
+       .resume                 = camera_core_resume,
+#endif
+       .shutdown               = NULL,
+};
+
+static struct platform_device camera_core_device = {
+       .name   = CAM_NAME,
+       .dev    = {
+                       .release        = NULL,
+                 },
+       .id     = 0,
+};
+
+void
+camera_core_cleanup(void)
+{
+       struct camera_device *cam = camera_dev;
+       struct video_device *vfd;
+
+       if (!cam)
+               return;
+
+       vfd = cam->vfd;
+       if (vfd) {
+               if (vfd->minor == -1) {
+                       /* The device never got registered, so release the 
+                       ** video_device struct directly
+                       */
+                       video_device_release(vfd);
+               } else {
+                       /* The unregister function will release the video_device
+                       ** struct as well as unregistering it.
+                       */
+                       video_unregister_device(vfd);
+                       driver_unregister(&camera_core_driver);
+                       platform_device_unregister(&camera_core_device);
+               }
+               cam->vfd = NULL;
+       }
+       if (cam->overlay_base) {
+               dma_free_coherent(NULL, cam->overlay_size,
+                                       (void *)cam->overlay_base, 
+                                       cam->overlay_base_phys);
+               cam->overlay_base = 0;
+       }       
+       cam->overlay_base_phys = 0;
+
+       cam->cam_sensor->cleanup(cam->sensor_data);
+       cam->cam_hardware->cleanup(cam->hardware_data);
+       kfree(cam);
+       camera_dev = NULL;
+
+       return;
+}
+
+
+int __init 
+camera_core_init(void)
+{
+       struct camera_device *cam;
+       struct video_device *vfd;
+
+       cam = kmalloc(sizeof(struct camera_device), GFP_KERNEL);
+       if (!cam) {
+               printk(KERN_ERR CAM_NAME ": could not allocate memory\n");
+               goto init_error;
+       }
+       memset(cam, 0, sizeof(struct camera_device));
+       
+       /* Save the pointer to camera device in a global variable */
+       camera_dev = cam;
+
+       /* initialize the video_device struct */
+       vfd = cam->vfd = video_device_alloc();
+       if (!vfd) {
+               printk(KERN_ERR CAM_NAME 
+                       ": could not allocate video device struct\n");
+               goto init_error;
+       }
+       
+       vfd->release = video_device_release;
+
+       strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name));
+       vfd->type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CHROMAKEY;
+       
+       /* need to register for a VID_HARDWARE_* ID in videodev.h */
+       vfd->hardware = 0;
+       vfd->fops = &camera_core_fops;
+       video_set_drvdata(vfd, cam);
+       vfd->minor = -1;
+
+       /* initialize the videobuf queue ops */
+       cam->vbq_ops.buf_setup = camera_core_vbq_setup;
+       cam->vbq_ops.buf_prepare = camera_core_vbq_prepare;
+       cam->vbq_ops.buf_queue = camera_core_vbq_queue;
+       cam->vbq_ops.buf_release = camera_core_vbq_release;
+
+       /* initilize the overlay interface */
+       cam->overlay_size = overlay_mem;
+       if (cam->overlay_size > 0)
+       {
+               cam->overlay_base = (unsigned long) dma_alloc_coherent(NULL,
+                                       cam->overlay_size,
+                                       (dma_addr_t *) &cam->overlay_base_phys,
+                                       GFP_KERNEL | GFP_DMA);
+               if (!cam->overlay_base) {
+                       printk(KERN_ERR CAM_NAME
+                               ": cannot allocate overlay framebuffer\n");
+                       goto init_error;
+               }
+       }
+       memset((void*)cam->overlay_base, 0, cam->overlay_size);
+       spin_lock_init(&cam->overlay_lock);
+       spin_lock_init(&cam->capture_lock);
+
+       /*Initialise the pointer to the sensor interface and camera interface */
+       cam->cam_sensor = &camera_sensor_if;
+       cam->cam_hardware = &camera_hardware_if;
+
+       /* initialize the camera interface */
+       cam->hardware_data = cam->cam_hardware->init();
+       if (!cam->hardware_data) {
+               printk(KERN_ERR CAM_NAME ": cannot initialize interface hardware\n");
+               goto init_error;
+       }
+        
+       /* initialize the spinlock used to serialize access to the image 
+        * parameters
+        */
+       spin_lock_init(&cam->img_lock);
+
+       /* initialize the streaming capture parameters */
+       cam->cparm.capability = V4L2_CAP_TIMEPERFRAME;
+       cam->cparm.readbuffers = 1;
+
+       /* Enable the xclk output.  The sensor may (and does, in the case of 
+        * the OV9640) require an xclk input in order for its initialization 
+        * routine to work.
+        */
+       cam->xclk = 21000000;   /* choose an arbitrary xclk frequency */
+       cam->xclk = cam->cam_hardware->set_xclk(cam->xclk, cam->hardware_data);
+
+       /* initialize the sensor and define a default capture format cam->pix */
+       cam->sensor_data = cam->cam_sensor->init(&cam->pix);
+       if (!cam->sensor_data) {
+               cam->cam_hardware->disable(cam->hardware_data);
+               printk(KERN_ERR CAM_NAME ": cannot initialize sensor\n");
+               goto init_error;
+       }
+
+       printk(KERN_INFO CAM_NAME ": %s interface with %s sensor\n",
+               cam->cam_hardware->name, cam->cam_sensor->name);
+
+       /* select an arbitrary default capture frame rate of 15fps */
+       cam->nominal_timeperframe.numerator = 1;
+       cam->nominal_timeperframe.denominator = 15;
+
+       /* calculate xclk based on the default capture format and default 
+        * frame rate
+        */
+       cam->xclk = cam->cam_sensor->calc_xclk(&cam->pix,
+               &cam->nominal_timeperframe, cam->sensor_data);
+       cam->cparm.timeperframe = cam->nominal_timeperframe;
+
+       /* initialise the wait queue */
+       init_waitqueue_head(&cam->new_video_frame);
+
+       /* Initialise the DMA structures */
+       camera_core_sgdma_init(cam);
+
+       /* Disable the Camera after detection */
+       cam->cam_hardware->disable(cam->hardware_data);
+
+       dev_set_drvdata(&camera_core_device.dev, (void *)cam);
+       if (platform_device_register(&camera_core_device) < 0) {
+               printk(KERN_ERR CAM_NAME
+                       ": could not register platform_device\n");
+               goto init_error;
+       }
+
+       if (driver_register(&camera_core_driver) < 0) {
+               printk(KERN_ERR CAM_NAME
+                       ": could not register driver\n");
+               platform_device_unregister(&camera_core_device);
+               goto init_error;
+       }
+       if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) {
+               printk(KERN_ERR CAM_NAME 
+                       ": could not register Video for Linux device\n");
+               platform_device_unregister(&camera_core_device);
+               driver_unregister(&camera_core_driver);
+               goto init_error;
+       }
+
+       printk(KERN_INFO CAM_NAME 
+               ": registered device video%d [v4l2]\n", vfd->minor);
+       return 0;
+
+init_error:
+       camera_core_cleanup();
+       return -ENODEV;
+}
+
+MODULE_AUTHOR("Texas Instruments.");
+MODULE_DESCRIPTION("OMAP Video for Linux camera driver");
+MODULE_LICENSE("GPL");
+module_param(video_nr, int, 0);
+MODULE_PARM_DESC(video_nr, 
+               "Minor number for video device (-1 ==> auto assign)");
+module_param(capture_mem, int, 0);
+MODULE_PARM_DESC(capture_mem,
+        "Maximum amount of memory for capture buffers (default 4800KB)");
+
+module_init(camera_core_init);
+module_exit(camera_core_cleanup);
+
+
diff --git a/drivers/media/video/omap/camera_core.h b/drivers/media/video/omap/camera_core.h
new file mode 100644 (file)
index 0000000..9ab336f
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *  drivers/media/video/omap/camera_core.h
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc. 
+ * 
+ * This package 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. 
+ * 
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
+ */
+
+#ifndef CAMERA_CORE__H
+#define CAMERA_CORE__H
+
+struct camera_fh;
+
+#include <media/video-buf.h>
+#include <asm/scatterlist.h>
+
+struct camera_device;
+typedef void (*dma_callback_t)(void *arg1, void *arg2);
+
+struct sgdma_state {
+       const struct scatterlist *sglist;
+       int sglen;              /* number of sglist entries */
+       int next_sglist;        /* index of next sglist entry to process */
+       int queued_sglist;      /* number of sglist entries queued for DMA */
+       unsigned long csr;      /* DMA return code */
+       dma_callback_t callback;
+       void *arg;
+};
+
+/* NUM_SG_DMA is the number of scatter-gather DMA transfers that can be queued.
+ */
+#define NUM_SG_DMA VIDEO_MAX_FRAME+2
+/* per-device data structure */
+struct camera_device {
+       struct device dev;
+       struct video_device *vfd;
+       
+       spinlock_t overlay_lock;        /* spinlock for overlay DMA counter */
+       int overlay_cnt;                /* count of queued overlay DMA xfers */
+       struct scatterlist overlay_sglist;
+       unsigned long overlay_base_phys;
+       unsigned long overlay_base;
+       unsigned long overlay_size;
+
+       spinlock_t vbq_lock;            /* spinlock for videobuf queues */
+       struct videobuf_queue_ops vbq_ops;      /* videobuf queue operations */
+       unsigned long field_count;      /* field counter for videobuf_buffer */
+
+       /* scatter-gather DMA management */
+       spinlock_t sg_lock;
+       int free_sgdma; /* number of free sg dma slots */
+       int next_sgdma; /* index of next sg dma slot to use */
+       struct sgdma_state sgdma[NUM_SG_DMA];
+       char in_use;
+
+       /* The img_lock is used to serialize access to the image parameters for 
+        * overlay and capture.  Need to use spin_lock_irq when writing to the 
+        * reading, streaming, and previewing parameters.  A regular spin_lock 
+        * will suffice for all other cases.
+        */
+       spinlock_t img_lock;
+       /* We allow reading from at most one filehandle at a time.
+        * non-NULL means reading is in progress.
+        */
+       struct camera_fh *reading;
+       /* We allow streaming from at most one filehandle at a time.  
+        * non-NULL means streaming is in progress.
+        */
+       struct camera_fh *streaming;
+       /* We allow previewing from at most one filehandle at a time.  
+        * non-NULL means previewing is in progress.
+        */
+       struct camera_fh *previewing;
+
+       /* capture parameters (frame rate, number of buffers) */
+       struct v4l2_captureparm cparm;
+
+       /* This is the frame period actually requested by the user. */
+       struct v4l2_fract nominal_timeperframe;
+       
+       /* frequency (in Hz) of camera interface xclk output */
+       unsigned long xclk;
+
+       /* Pointer to the sensor interface ops */
+       struct camera_sensor *cam_sensor;
+       void *sensor_data;
+       
+       /* Pointer to the camera interface hardware ops */
+       struct camera_hardware *cam_hardware;
+       void *hardware_data;
+
+       /* pix defines the size and pixel format of the image captured by the 
+        * sensor.  This also defines the size of the framebuffers.  The 
+        * same pool of framebuffers is used for video capture and video 
+        * overlay.  These parameters are set/queried by the 
+        * VIDIOC_S_FMT/VIDIOC_G_FMT ioctls with a CAPTURE buffer type.
+        */
+       struct v4l2_pix_format pix;
+
+       /* crop defines the size and offset of the video overlay source window 
+        * within the framebuffer.  These parameters are set/queried by the 
+        * VIDIOC_S_CROP/VIDIOC_G_CROP ioctls with an OVERLAY buffer type.  
+        * The cropping rectangle allows a subset of the captured image to be 
+        * previewed.  It only affects the portion of the image previewed, not 
+        * captured; the entire camera image is always captured.
+        */
+       struct v4l2_rect crop;
+
+       /* win defines the size and offset of the video overlay target window 
+        * within the video display.  These parameters are set/queried by the 
+        * VIDIOC_S_FMT/VIDIOC_G_FMT ioctls with an OVERLAY buffer type.
+        */
+       struct v4l2_window win;
+
+       /* fbuf reflects the size of the video display.  It is queried with the 
+        * VIDIOC_G_FBUF ioctl.  The size of the video display cannot be 
+        * changed with the VIDIOC_S_FBUF ioctl.
+        */
+       struct v4l2_framebuffer fbuf;
+
+       /* end of generic stuff, the above should be common to all omaps */
+
+       /* note, 2420 uses videobuf to do caprure, it is more memory efficient
+          we need 1710 and 2420 do capture in the same way */
+       /* Variables to store the capture state */
+       /* Wait till DMA is completed */
+       wait_queue_head_t new_video_frame;
+       char capture_completed;
+       char capture_started;
+       spinlock_t capture_lock;
+       struct scatterlist capture_sglist;
+       unsigned long capture_base;
+       unsigned long capture_base_phys;
+
+       char active;
+};
+
+/* per-filehandle data structure */
+struct camera_fh {
+       struct camera_device *cam;
+       enum v4l2_buf_type type;
+       struct videobuf_queue vbq;
+};
+
+#define CAM_NAME "omap-camera"
+
+#endif /* CAMERA_CORE__H */
diff --git a/drivers/media/video/omap/camera_hw_if.h b/drivers/media/video/omap/camera_hw_if.h
new file mode 100644 (file)
index 0000000..2c941b5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  drivers/media/video/omap/camera_hw_if.h
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc. 
+ * 
+ * Camera interface to OMAP camera capture drivers
+ * Camera interface hardware driver should implement this interface
+ *
+ * This package 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. 
+ * 
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
+ */
+#ifndef OMAP_CAMERA_HW_IF_H
+#define OMAP_CAMERA_HW_IF_H
+
+#define LEN_HW_IF_NAME         31
+
+struct sgdma_state;
+
+struct camera_hardware {
+       unsigned int version;  //version of camera driver module
+       char name[LEN_HW_IF_NAME + 1];
+
+       void *(*init)(void);
+       int (*cleanup)(void *);
+
+       int (*open)(void *);  /* acquire h/w resources (irq,DMA), etc. */
+       int (*close)(void *); /* free h/w resources, stop i/f */
+
+       int (*enable)(void *);
+       int (*disable)(void *);
+
+       int (*abort)(void *);
+
+       int (*set_xclk)(int, void *);
+
+       int (*init_dma)(void *);
+       int (*start_dma)(struct sgdma_state *, void (*)(void *arg1, void *arg2),
+                       void *, void *, void *);
+       int (*finish_dma)(void *);
+};
+#endif /* OMAP_CAMERA_HW_IF_H */
diff --git a/drivers/media/video/omap/omap16xxcam.c b/drivers/media/video/omap/omap16xxcam.c
new file mode 100644 (file)
index 0000000..6f85bd2
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+ * drivers/media/video/omap/omap16xxcam.c
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc. 
+ * 
+ * Video-for-Linux (Version 2) camera capture driver for
+ * the OMAP H2 and H3 camera controller.
+ *
+ * leverage some code from CEE distribution 
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * 
+ * This package 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. 
+ * 
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
+ */
+#include <linux/config.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/clock.h>
+
+#include "omap16xxcam.h"
+#include "camera_hw_if.h"
+#include "camera_core.h"
+  
+#define CONF_CAMERAIF_RESET_R 5
+#define EN_PER   0
+
+/* NUM_CAMDMA_CHANNELS is the number of logical channels used for
+ * DMA data transfer.
+ */
+#define NUM_CAMDMA_CHANNELS 2
+
+typedef struct {
+        unsigned int ctrlclock;     /* 00 */
+        unsigned int it_status;     /* 04 */
+        unsigned int mode;          /* 08 */
+        unsigned int status;        /* 0C */
+        unsigned int camdata;       /* 10 */
+        unsigned int gpio;         /* 14 */
+        unsigned int peak_counter;  /* 18 */
+} camera_regs_t;
+
+struct camdma_state {
+       dma_callback_t callback;
+       void *arg1;
+       void *arg2;
+};
+
+struct omap16xxcam {
+       camera_regs_t *camera_regs;
+       unsigned long iobase_phys;
+
+       /* frequncy (in Hz) of camera interface functional clock (ocp_clk) */
+       unsigned long ocp_clk; 
+
+       /* dma related stuff */
+       spinlock_t dma_lock;
+       int free_dmach;
+       int next_dmach;
+       struct camdma_state camdma[NUM_CAMDMA_CHANNELS];
+       int dma_channel_number1;
+       int dma_channel_number2;
+
+       wait_queue_head_t vsync_wait;
+       
+       int new;
+};
+static struct omap16xxcam hardware_data;
+   
+static int omap16xxcam_set_xclk(int, void *);
+static void omap16xx_cam_dma_link_callback(int, unsigned short, void *);
+
+/* Clears the camera data FIFO by setting RAZ_FIFO bit in MODE configuration
+   register. */
+static void
+omap16xx_cam_clear_fifo(struct omap16xxcam *data)
+{
+       data->camera_regs->mode |= RAZ_FIFO;
+       udelay(10);
+       data->camera_regs->mode &= ~RAZ_FIFO;
+}
+  
+static void
+omap16xx_cam_reset(struct omap16xxcam *data, int yes)
+{
+       if (machine_is_omap_h3())
+               data->camera_regs->gpio = yes ? 0 : 1;
+       else
+               data->camera_regs->gpio = yes ? 1 : 0;
+}
+
+static void 
+omap16xx_cam_init(void)
+{
+       /*
+        * FIXME - Use mux API's instead of directly writing in to MUX registers
+        */
+       omap_writel(omap_readl(FUNC_MUX_CTRL_4) & ~(0x1ff << 21), FUNC_MUX_CTRL_4);
+       omap_writel(0, FUNC_MUX_CTRL_5);
+       omap_writel(omap_readl(PULL_DWN_CTRL_0) & ~(0x1FFF << 17), PULL_DWN_CTRL_0);
+       omap_writel(omap_readl(PU_PD_SEL_0) & ~(0x1FFF << 17), PU_PD_SEL_0);
+
+       omap_writel(0xeaef, COMP_MODE_CTRL_0);
+       omap_writel(omap_readl(OMAP1610_RESET_CONTROL) & ~(1 << CONF_CAMERAIF_RESET_R),
+                       OMAP1610_RESET_CONTROL);
+       omap_writel(omap_readl(OMAP1610_RESET_CONTROL) | (1 << CONF_CAMERAIF_RESET_R),
+                       OMAP1610_RESET_CONTROL);
+    
+       /* Enable peripheral reset */
+       omap_writew(omap_readw(ARM_RSTCT2) | (1 << EN_PER), ARM_RSTCT2); 
+
+       /* enable peripheral clock */
+       if (machine_is_omap_h3())
+               clk_enable(clk_get(0, "tc2_ck"));
+       else {
+               clk_enable(clk_get(0, "armper_ck"));
+               clk_enable(clk_get(0, "armxor_ck"));
+       }               
+}
+
+static void
+omap16xx_cam_waitfor_syncedge(struct omap16xxcam *data, u32 edge_mask)
+{
+       data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT) | edge_mask;
+       do {
+               interruptible_sleep_on(&data->vsync_wait);
+       } while (signal_pending(current));
+}
+
+static void
+omap16xx_cam_configure_dma(struct omap16xxcam *data)
+{
+
+       data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT)
+                        | EN_DMA | EN_FIFO_FULL;
+       data->camera_regs->ctrlclock |= LCLK_EN; 
+}
+
+/* acquire h/w resources DMA */
+static int
+omap16xx_cam_link_open(struct omap16xxcam *data)
+{
+       int ret;
+
+       /* Acquire first dma channel */
+       if ((ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, 
+                               "camera dma 1", omap16xx_cam_dma_link_callback,
+                               (void *)data, &data->dma_channel_number1))) {
+                return ret;
+       }
+       /* Acquire second dma channel */
+       if ((ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, 
+                               "camera dma 2", omap16xx_cam_dma_link_callback,
+                               (void *)data, &data->dma_channel_number2))) {
+                printk ("No DMA available for camera\n");
+                return ret;
+        }
+       data->next_dmach = data->dma_channel_number1;
+       OMAP_DMA_CLNK_CTRL_REG(data->dma_channel_number1) =
+               data->dma_channel_number2;
+       OMAP_DMA_CLNK_CTRL_REG(data->dma_channel_number2) =
+               data->dma_channel_number1;
+
+       return 0;
+}
+
+/* free h/w resources, stop i/f */
+static int
+omap16xx_cam_link_close(struct omap16xxcam *data)
+{
+       /* free dma channels */
+       omap_stop_dma(data->dma_channel_number1);
+       omap_stop_dma(data->dma_channel_number2);
+
+       omap_free_dma (data->dma_channel_number1);
+       omap_free_dma (data->dma_channel_number2);
+
+       return 0;
+}
+
+/* dma callback routine. */
+static void
+omap16xx_cam_dma_link_callback(int lch, unsigned short ch_status, void *data)
+{
+       int count;
+       void *arg1, *arg2;
+       struct sgdma_state *sgdma = sgdma;
+       struct omap16xxcam *cam = (struct omap16xxcam *)data;
+       dma_callback_t callback;
+
+       spin_lock(&cam->dma_lock);
+       if (cam->free_dmach == 2)
+       {
+               printk("callback all CHANNELS WERE IDLE \n");
+               spin_unlock(&cam->dma_lock);
+               return;
+       }
+       if (cam->free_dmach == 0) {
+               lch = cam->next_dmach;
+       } else {
+               lch = cam->next_dmach == cam->dma_channel_number1 ? 
+                       cam->dma_channel_number2 : cam->dma_channel_number1;
+       }
+
+       while (cam->free_dmach < 2)
+       {
+               if (OMAP_DMA_CCR_REG(lch) & (1 << 7))
+                       break;  
+
+               count = (lch == cam->dma_channel_number2) ? 1 : 0;
+
+               callback = cam->camdma[count].callback;
+               arg1 = cam->camdma[count].arg1;
+               arg2 = cam->camdma[count].arg2;
+               cam->free_dmach++;
+
+               spin_unlock(&cam->dma_lock);            
+               callback(arg1, arg2);
+               spin_lock(&cam->dma_lock);
+
+               lch = (lch == cam->dma_channel_number2) ? cam->dma_channel_number1 :
+                                                       cam->dma_channel_number2;
+       }
+       spin_unlock(&cam->dma_lock);
+       
+}
+
+static irqreturn_t
+omap16xx_cam_isr(int irq, void *client_data, struct pt_regs *regs)
+{
+       struct omap16xxcam *data = (struct omap16xxcam *)client_data;
+       unsigned int itstat = data->camera_regs->it_status;
+
+       /* VSYNC UP interrupt, start filling FIFO and enabling DMA */
+       if (itstat & V_UP) {            
+               data->camera_regs->mode &= ~EN_V_UP;
+               omap16xx_cam_clear_fifo(data);  
+               omap16xx_cam_configure_dma(data);
+               omap_start_dma(data->next_dmach);
+               wake_up_interruptible(&data->vsync_wait);
+       }
+
+       if (itstat & V_DOWN) {
+               data->camera_regs->mode &= ~EN_V_DOWN;
+               wake_up_interruptible(&data->vsync_wait);
+       }
+
+       if (itstat & H_UP)
+               printk("H_UP\n");
+       
+       if (itstat & H_DOWN)
+               printk("H_DOWN\n");
+       
+       if (itstat & FIFO_FULL) {
+               omap16xx_cam_clear_fifo(data);  
+               printk("FIFO_FULL\n");
+       }
+       
+       if (itstat & DATA_XFER)
+               printk("DATA_TRANS\n");
+       
+       return IRQ_HANDLED;
+}
+/* ------------- below are interface functions ----------------- */
+/* ------------- these functions are named omap16xxcam_<name> -- */
+static int
+omap16xxcam_init_dma(void *priv)
+{
+       int ch;
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+
+       data->free_dmach = 2;
+       for (ch = 0; ch < 2; ++ch) {
+               data->camdma[ch].callback = NULL;
+               data->camdma[ch].arg1 = NULL;
+               data->camdma[ch].arg2 = NULL;
+       }
+
+       return 0;
+}
+
+/* start the dma of chains */
+static int 
+omap16xxcam_start_dma(struct sgdma_state *sgdma,
+               dma_callback_t callback, void *arg1, void *arg2, void *priv)
+{
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+       struct scatterlist *sglist;
+       unsigned long irqflags;
+       int dmach;
+       int prev_dmach;
+       int count;
+
+       spin_lock_irqsave(&data->dma_lock, irqflags);
+       sglist = (struct scatterlist *)(sgdma->sglist + sgdma->next_sglist);
+
+       if (!data->free_dmach) {
+               spin_unlock_irqrestore(&data->dma_lock, irqflags);
+               return -EBUSY;
+       } 
+       dmach = data->next_dmach;
+       count = (dmach == data->dma_channel_number2) ? 1:0;
+       data->camdma[count].callback = callback;
+       data->camdma[count].arg1 = arg1;
+       data->camdma[count].arg2 = arg2;
+       
+       if (machine_is_omap_h3())
+               omap_set_dma_src_params(dmach, OMAP_DMA_PORT_OCP_T1,
+                           OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG,
+                           0, 0);
+       else
+               omap_set_dma_src_params(dmach, OMAP_DMA_PORT_TIPB,
+                           OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG,
+                           0, 0);
+
+       omap_set_dma_dest_params(dmach, OMAP_DMA_PORT_EMIFF,
+                            OMAP_DMA_AMODE_POST_INC, sg_dma_address(sglist),
+                            0, 0);
+
+       omap_set_dma_transfer_params(dmach, OMAP_DMA_DATA_TYPE_S32,
+                       FIFO_TRIGGER_LVL, 
+                       sg_dma_len(sglist)/(4 * FIFO_TRIGGER_LVL), 
+                       OMAP_DMA_SYNC_FRAME,
+                       0, 0);
+
+       OMAP_DMA_CLNK_CTRL_REG(dmach) &= ~( 1<< 15);
+
+       prev_dmach = (dmach == data->dma_channel_number2) ? 
+               data->dma_channel_number1 : data->dma_channel_number2;
+       
+       if (data->new) {
+               data->new = 0;
+               omap16xx_cam_waitfor_syncedge(data, EN_V_UP);
+       } else {
+               if (OMAP_DMA_CCR_REG(prev_dmach) & (1 << 7))
+                       OMAP_DMA_CLNK_CTRL_REG(prev_dmach) |= (1 << 15);
+               else {
+                       /* no transfer is in progress */
+                       omap_start_dma(dmach);
+               }       
+       }
+       
+       data->next_dmach = prev_dmach; 
+       data->free_dmach--;
+       spin_unlock_irqrestore(&data->dma_lock, irqflags);
+       return 0;
+}
+int static
+omap16xxcam_finish_dma(void *priv)
+{
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+
+       while (data->free_dmach < 2)
+               mdelay(1);
+
+       return 0;
+}
+
+
+/* Enables the camera. Takes camera out of reset. Enables the clocks. */ 
+static int
+omap16xxcam_enable(void *priv)
+{
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+
+       omap16xx_cam_reset(data, 1);
+       
+       /* give clock to camera_module */
+       data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT);
+       data->camera_regs->ctrlclock = MCLK_EN | CAMEXCLK_EN;
+
+       omap16xx_cam_clear_fifo(data);
+
+       /* wait for camera to settle down */
+       mdelay(5);
+
+       return 0;
+}
+/* Disables all the camera clocks. Put the camera interface in reset. */
+static int
+omap16xxcam_disable(void *priv)
+{      
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+
+       omap16xx_cam_clear_fifo(data);
+
+       data->camera_regs->ctrlclock = 0x00000000;     
+       data->camera_regs->mode = 0x00000000;
+       
+       omap16xx_cam_reset(data, 0);
+
+       return 0;
+}
+
+/* Abort the data transfer */
+static int
+omap16xxcam_abort(void *priv)
+{
+       return omap16xxcam_disable(priv);
+}
+
+static int
+omap16xxcam_set_xclk(int xclk, void *priv)
+{      
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+       int xclk_val;
+       int divisor = 1;
+       divisor = data->ocp_clk/xclk;
+       if ( divisor * xclk < data->ocp_clk)
+               ++divisor; 
+
+       switch (divisor) {
+               case 1:
+               case 2:
+                       xclk_val = FOSCMOD_TC2_CK2;
+                       break;
+               case 3:
+                       xclk_val = FOSCMOD_TC2_CK3;
+                       break;
+               case 4:
+               case 5:
+               case 6:
+               case 7:
+                       xclk_val = FOSCMOD_TC2_CK4;
+                       break;
+               case 8:
+               case 9:
+                       xclk_val = FOSCMOD_TC2_CK8;
+                       break;
+               case 10:
+               case 11:
+                       xclk_val = FOSCMOD_TC2_CK10;
+                       break;
+               case 12:
+               case 13:
+               case 14:
+               case 15:
+                       xclk_val = FOSCMOD_TC2_CK12;
+                       break;
+               case 16:
+                       xclk_val = FOSCMOD_TC2_CK16;
+                       break;
+               default:
+                       xclk_val = FOSCMOD_TC2_CK16;
+       }
+       
+       /* follow the protocol to change the XCLK clock */
+       data->camera_regs->ctrlclock &= ~CAMEXCLK_EN;
+       data->camera_regs->ctrlclock |= xclk_val;
+       data->camera_regs->ctrlclock |= CAMEXCLK_EN;
+
+       return (data->ocp_clk/divisor);
+}
+
+static int
+omap16xxcam_open(void *priv)
+{
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+       int ret;
+
+       if ((ret = request_irq(INT_CAMERA, omap16xx_cam_isr, SA_INTERRUPT, 
+                                       "camera", data))) {
+               printk("FAILED to aquire irq\n");
+               return ret;
+       }
+
+       data->new = 1;
+       omap16xxcam_enable(data);
+       omap16xxcam_init_dma(data);
+
+       return omap16xx_cam_link_open(data);
+}
+
+static int
+omap16xxcam_close(void *priv)
+{
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+
+       omap16xxcam_disable(priv);
+        
+       free_irq(INT_CAMERA, data);
+       
+       return omap16xx_cam_link_close(data);
+}
+
+static int
+omap16xxcam_cleanup(void *priv)
+{
+       struct omap16xxcam *data = (struct omap16xxcam *) priv;
+
+       omap16xxcam_disable(data);
+       if (machine_is_omap_h3()) {
+               if (data->camera_regs) {        
+                       iounmap((void *)data->camera_regs);
+                       data->camera_regs= NULL;
+               }
+       }
+
+       if (data->iobase_phys) {
+               release_mem_region(data->iobase_phys, CAMERA_IOSIZE);
+               data->iobase_phys = 0;
+       }
+
+       return 0;
+}
+
+/* Initialise the OMAP camera interface */
+static void *
+omap16xxcam_init(void)
+{
+       unsigned long cam_iobase;
+
+       if (!request_region(CAMERA_BASE, CAMERA_IOSIZE, "OAMP16xx Camera")) {
+               printk ("OMAP16XX Parallel Camera Interface is already in use\n");
+               return NULL;
+       }
+
+       if (machine_is_omap_h3()) {
+               cam_iobase = (unsigned long) ioremap (CAMERA_BASE, CAMERA_IOSIZE);
+               if (!cam_iobase) {
+                       printk("CANNOT MAP CAMERA REGISTER\n");
+                       return NULL;
+               }
+       }
+       else
+               cam_iobase = io_p2v(CAMERA_BASE);
+
+       /* Set the base address of the camera registers */
+       hardware_data.camera_regs = (camera_regs_t *)cam_iobase;
+       hardware_data.iobase_phys = (unsigned long) CAMERA_BASE;
+       /* get the input clock value to camera interface and store it */
+       if (machine_is_omap_h3())
+               hardware_data.ocp_clk = clk_get_rate(clk_get(0, "tc_ck"));
+       else
+               hardware_data.ocp_clk = clk_get_rate(clk_get(0, "mpuper_ck"));
+
+       /* Init the camera IF */
+       omap16xx_cam_init();
+       /* enable it. This is needed for sensor detection */
+       omap16xxcam_enable((void*)&hardware_data);
+       /* Init dma data */
+       spin_lock_init(&hardware_data.dma_lock);
+
+       init_waitqueue_head(&hardware_data.vsync_wait);
+       return (void*)&hardware_data;
+}
+
+struct camera_hardware camera_hardware_if = {
+       version         : 0x01, 
+       name            : "OMAP16xx Camera Parallel", 
+       init            : omap16xxcam_init,
+       cleanup         : omap16xxcam_cleanup,
+       open            : omap16xxcam_open, 
+       close           : omap16xxcam_close,
+       enable          : omap16xxcam_enable, 
+       disable         : omap16xxcam_disable,
+       abort           : omap16xxcam_abort,
+       set_xclk        : omap16xxcam_set_xclk,
+       init_dma        : omap16xxcam_init_dma,
+       start_dma       : omap16xxcam_start_dma,
+       finish_dma      : omap16xxcam_finish_dma,
+};
+
diff --git a/drivers/media/video/omap/omap16xxcam.h b/drivers/media/video/omap/omap16xxcam.h
new file mode 100644 (file)
index 0000000..14de5b7
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  drivers/media/video/omap/omap16xxcam.h
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc. 
+ * 
+ * This package 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. 
+ * 
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
+ */
+#ifndef OMAP_16XX_CAM_H
+#define OMAP_16XX_CAM_H
+
+#define DMA_ELEM_SIZE   4
+#define FIFO_TRIGGER_LVL (32)
+
+/*
+ * ---------------------------------------------------------------------------
+ *  OMAP1610 Camera Interface
+ * ---------------------------------------------------------------------------
+ */
+
+#ifdef CONFIG_MACH_OMAP_H3
+#define CAMERA_BASE          (0x2007d800)
+#else
+#define CAMERA_BASE          (IO_PHYS + 0x6800)
+#endif
+
+#define CAM_CTRLCLOCK_REG    (CAMERA_BASE + 0x00)
+#define CAM_IT_STATUS_REG    (CAMERA_BASE + 0x04)
+#define CAM_MODE_REG         (CAMERA_BASE + 0x08)
+#define CAM_STATUS_REG       (CAMERA_BASE + 0x0C)
+#define CAM_CAMDATA_REG      (CAMERA_BASE + 0x10)
+#define CAM_GPIO_REG         (CAMERA_BASE + 0x14)
+#define CAM_PEAK_CTR_REG     (CAMERA_BASE + 0x18)
+#define CAMERA_IOSIZE        0x1C
+
+/* CTRLCLOCK bit shifts */
+#define FOSCMOD_BIT                    0
+#define FOSCMOD_MASK                   (0x7 << FOSCMOD_BIT)
+#define FOSCMOD_12MHz          0x0
+#define        FOSCMOD_6MHz            0x2
+#define        FOSCMOD_9_6MHz          0x4
+#define        FOSCMOD_24MHz           0x5
+#define        FOSCMOD_8MHz            0x6
+#define        FOSCMOD_TC2_CK2         0x3
+#define        FOSCMOD_TC2_CK3         0x1
+#define        FOSCMOD_TC2_CK4         0x5
+#define        FOSCMOD_TC2_CK8         0x0
+#define        FOSCMOD_TC2_CK10        0x4
+#define        FOSCMOD_TC2_CK12        0x6
+#define        FOSCMOD_TC2_CK16        0x2
+#define        POLCLK                  (1<<3)
+#define        CAMEXCLK_EN             (1<<4)
+#define        MCLK_EN                 (1<<5)
+#define        DPLL_EN                 (1<<6)
+#define        LCLK_EN                 (1<<7)
+
+/* IT_STATUS bit shifts */
+#define V_UP           (1<<0)
+#define V_DOWN         (1<<1)
+#define H_UP           (1<<2)
+#define H_DOWN         (1<<3)
+#define FIFO_FULL      (1<<4)
+#define DATA_XFER      (1<<5)
+
+/* MODE bit shifts */
+#define CAMOSC         (1<<0)
+#define IMGSIZE_BIT    1
+#define IMGSIZE_MASK   (0x3 << IMGSIZE_BIT)
+#define        IMGSIZE_CIF      (0x0 << IMGSIZE_BIT)    /* 352x288 */
+#define        IMGSIZE_QCIF     (0x1 << IMGSIZE_BIT)    /* 176x144 */
+#define        IMGSIZE_VGA      (0x2 << IMGSIZE_BIT)    /* 640x480 */
+#define        IMGSIZE_QVGA     (0x3 << IMGSIZE_BIT)    /* 320x240 */
+#define ORDERCAMD      (1<<3)
+#define EN_V_UP        (1<<4)
+#define EN_V_DOWN      (1<<5)
+#define EN_H_UP        (1<<6)
+#define EN_H_DOWN      (1<<7)
+#define EN_DMA         (1<<8)
+#define THRESHOLD      (1<<9)
+#define THRESHOLD_BIT  9
+#define THRESHOLD_MASK (0x7f<<9)
+#define EN_NIRQ        (1<<16)
+#define EN_FIFO_FULL   (1<<17)
+#define RAZ_FIFO       (1<<18)
+
+/* STATUS bit shifts */
+#define VSTATUS        (1<<0)
+#define HSTATUS        (1<<1)
+
+/* GPIO bit shifts */
+#define CAM_RST        (1<<0)
+
+
+#define XCLK_6MHZ     6000000
+#define XCLK_8MHZ     8000000
+#define XCLK_9_6MHZ   9000000
+#define XCLK_12MHZ   12000000
+#define XCLK_24MHZ   24000000
+
+#endif /* OMAP_16XX_CAM_H */
diff --git a/drivers/media/video/omap/ov9640.h b/drivers/media/video/omap/ov9640.h
new file mode 100644 (file)
index 0000000..4cdba05
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * drivers/media/video/omap/ov9640.h
+ *
+ * Register definitions for the OmniVision OV9640 CameraChip.
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License 
+ * version 2. This program is licensed "as is" without any warranty of any 
+ * kind, whether express or implied.
+ */
+
+#ifndef OV9640_H
+#define OV9640_H
+
+/* The OV9640 I2C sensor chip has a fixed slave address of 0x30. */
+#ifdef CONFIG_OMAP24XX_VIRTIO
+#define OV9640_I2C_ADDR                0x60
+#else
+#define OV9640_I2C_ADDR                0x30
+#endif
+
+/* define register offsets for the OV9640 sensor chip */
+#define OV9640_GAIN            0x00
+#define OV9640_BLUE            0x01
+#define OV9640_RED             0x02
+#define OV9640_VREF            0x03
+#define OV9640_COM1            0x04
+#define OV9640_BAVE            0x05
+#define OV9640_GEAVE           0x06
+#define OV9640_RAVE            0x08
+#define OV9640_COM2            0x09
+#define OV9640_PID             0x0A
+#define OV9640_VER             0x0B
+#define OV9640_COM3            0x0C
+#define OV9640_COM4            0x0D
+#define OV9640_COM5            0x0E
+#define OV9640_COM6            0x0F
+#define OV9640_AECH            0x10
+#define OV9640_CLKRC           0x11
+#define OV9640_COM7            0x12
+#define OV9640_COM8            0x13
+#define OV9640_COM9            0x14
+#define OV9640_COM10           0x15
+#define OV9640_HSTRT           0x17
+#define OV9640_HSTOP           0x18
+#define OV9640_VSTRT           0x19
+#define OV9640_VSTOP           0x1A
+#define OV9640_PSHFT           0x1B
+#define OV9640_MIDH            0x1C
+#define OV9640_MIDL            0x1D
+#define OV9640_MVFP            0x1E
+#define OV9640_LAEC            0x1F
+#define OV9640_BOS             0x20
+#define OV9640_GBOS            0x21
+#define OV9640_GROS            0x22
+#define OV9640_ROS             0x23
+#define OV9640_AEW             0x24
+#define OV9640_AEB             0x25
+#define OV9640_VPT             0x26
+#define OV9640_BBIAS           0x27
+#define OV9640_GBBIAS          0x28
+#define OV9640_EXHCH           0x2A
+#define OV9640_EXHCL           0x2B
+#define OV9640_RBIAS           0x2C
+#define OV9640_ADVFL           0x2D
+#define OV9640_ADVFH           0x2E
+#define OV9640_YAVE            0x2F
+#define OV9640_HSYST           0x30
+#define OV9640_HSYEN           0x31
+#define OV9640_HREF            0x32
+#define OV9640_CHLF            0x33
+#define OV9640_ARBLM           0x34
+#define OV9640_ADC             0x37
+#define OV9640_ACOM            0x38
+#define OV9640_OFON            0x39
+#define OV9640_TSLB            0x3A
+#define OV9640_COM11           0x3B
+#define OV9640_COM12           0x3C
+#define OV9640_COM13           0x3D
+#define OV9640_COM14           0x3E
+#define OV9640_EDGE            0x3F
+#define OV9640_COM15           0x40
+#define OV9640_COM16           0x41
+#define OV9640_COM17           0x42
+#define OV9640_MTX1            0x4F
+#define OV9640_MTX2            0x50
+#define OV9640_MTX3            0x51
+#define OV9640_MTX4            0x52
+#define OV9640_MTX5            0x53
+#define OV9640_MTX6            0x54
+#define OV9640_MTX7            0x55
+#define OV9640_MTX8            0x56
+#define OV9640_MTX9            0x57
+#define OV9640_MTXS            0x58
+#define OV9640_LCC1            0x62
+#define OV9640_LCC2            0x63
+#define OV9640_LCC3            0x64
+#define OV9640_LCC4            0x65
+#define OV9640_LCC5            0x66
+#define OV9640_MANU            0x67
+#define OV9640_MANV            0x68
+#define OV9640_HV              0x69
+#define OV9640_MBD             0x6A
+#define OV9640_DBLV            0x6B
+#define OV9640_GSP1            0x6C
+#define OV9640_GSP2            0x6D
+#define OV9640_GSP3            0x6E
+#define OV9640_GSP4            0x6F
+#define OV9640_GSP5            0x70
+#define OV9640_GSP6            0x71
+#define OV9640_GSP7            0x72
+#define OV9640_GSP8            0x73
+#define OV9640_GSP9            0x74
+#define OV9640_GSP10           0x75
+#define OV9640_GSP11           0x76
+#define OV9640_GSP12           0x77
+#define OV9640_GSP13           0x78
+#define OV9640_GSP14           0x79
+#define OV9640_GSP15           0x7A
+#define OV9640_GSP16           0x7B
+#define OV9640_GST1            0x7C
+#define OV9640_GST2            0x7D
+#define OV9640_GST3            0x7E
+#define OV9640_GST4            0x7F
+#define OV9640_GST5            0x80
+#define OV9640_GST6            0x81
+#define OV9640_GST7            0x82
+#define OV9640_GST8            0x83
+#define OV9640_GST9            0x84
+#define OV9640_GST10           0x85
+#define OV9640_GST11           0x86
+#define OV9640_GST12           0x87
+#define OV9640_GST13           0x88
+#define OV9640_GST14           0x89
+#define OV9640_GST15           0x8A
+
+#define OV9640_NUM_REGS                (OV9640_GST15 + 1)
+
+#define OV9640_PID_MAGIC       0x96    /* high byte of product ID number */
+#define OV9640_VER_REV2                0x48    /* low byte of product ID number */
+#define OV9640_VER_REV3                0x49    /* low byte of product ID number */
+#define OV9640_MIDH_MAGIC      0x7F    /* high byte of mfg ID */
+#define OV9640_MIDL_MAGIC      0xA2    /* low byte of mfg ID */
+
+/* define a structure for ov9640 register initialization values */
+struct ov9640_reg {
+       unsigned char reg;
+       unsigned char val;
+};
+
+enum image_size { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA };
+enum pixel_format { YUV, RGB565, RGB555 };
+#define NUM_IMAGE_SIZES 7
+#define NUM_PIXEL_FORMATS 3
+
+struct capture_size {
+       unsigned long width;
+       unsigned long height;
+};
+
+/* Array of image sizes supported by OV9640.  These must be ordered from 
+ * smallest image size to largest.
+ */
+const static struct capture_size ov9640_sizes[] = {
+       {   88,  72 },  /* QQCIF */
+       {  160, 120 },  /* QQVGA */
+       {  176, 144 },  /* QCIF */
+       {  320, 240 },  /* QVGA */
+       {  352, 288 },  /* CIF */
+       {  640, 480 },  /* VGA */
+       { 1280, 960 },  /* SXGA */
+};
+
+#endif /* ifndef OV9640_H */
+
diff --git a/drivers/media/video/omap/sensor_if.h b/drivers/media/video/omap/sensor_if.h
new file mode 100644 (file)
index 0000000..984ba55
--- /dev/null
@@ -0,0 +1,49 @@
+
+/*
+ * drivers/media/video/omap/sensor_if.h
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc. 
+ * 
+ * Sensor interface to OMAP camera capture drivers
+ * Sensor driver should implement this interface
+ *
+ * This package 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. 
+ * 
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
+ */
+#ifndef OMAP_SENSOR_IF_H
+#define OMAP_SENSOR_IF_H
+#define LEN_SENSOR_NAME                31
+
+struct camera_sensor {
+       unsigned int version;
+       char name[LEN_SENSOR_NAME + 1];
+
+       void *(*init)(struct v4l2_pix_format *);
+       int (*cleanup)(void *);
+
+       int (*power_on)(void *);
+       int (*power_off)(void *);
+
+       int (*enum_pixformat)(struct v4l2_fmtdesc *, void *);
+       int (*try_format) (struct v4l2_pix_format *, void *);
+
+       unsigned long (*calc_xclk) (struct v4l2_pix_format *,
+               struct v4l2_fract *, void *);
+
+       int (*configure) (struct v4l2_pix_format *, unsigned long,
+                                         struct v4l2_fract *, void *);
+
+       int (*query_control) (struct v4l2_queryctrl *, void *);
+       int (*get_control) (struct  v4l2_control *, void *);
+       int (*set_control) (struct  v4l2_control *, void *);
+
+};
+       
+#endif
diff --git a/drivers/media/video/omap/sensor_ov9640.c b/drivers/media/video/omap/sensor_ov9640.c
new file mode 100644 (file)
index 0000000..c48f401
--- /dev/null
@@ -0,0 +1,1181 @@
+
+/*
+ * drivers/media/video/omap/sensor_ov9640.c
+ *
+ * Ov9640 Sensor driver for OMAP camera sensor interface
+ *
+ * Author: Andy Lowe (source@mvista.com)
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License 
+ * version 2. This program is licensed "as is" without any warranty of any 
+ * kind, whether express or implied.
+ */
+
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <media/video-buf.h>
+#include <linux/delay.h>
+#include <asm/mach-types.h>
+#include <asm/arch/gpioexpander.h>
+
+#include "sensor_if.h"
+#include "ov9640.h"
+
+#define CAMERA_OV9640
+#ifdef CAMERA_OV9640
+
+struct ov9640_sensor {
+       /* I2C parameters */
+       struct i2c_client client;
+       struct i2c_driver driver;
+       int ver; /* OV9640 version */
+};
+
+static struct ov9640_sensor ov9640;
+
+/* list of image formats supported by OV9640 sensor */
+const static struct v4l2_fmtdesc ov9640_formats[] = {
+       {
+               /* Note:  V4L2 defines RGB565 as:
+                *
+                *      Byte 0                    Byte 1
+                *      g2 g1 g0 r4 r3 r2 r1 r0   b4 b3 b2 b1 b0 g5 g4 g3
+                *
+                * We interpret RGB565 as:
+                *
+                *      Byte 0                    Byte 1
+                *      g2 g1 g0 b4 b3 b2 b1 b0   r4 r3 r2 r1 r0 g5 g4 g3
+                */
+               .description    = "RGB565, le",
+               .pixelformat    = V4L2_PIX_FMT_RGB565,
+       },{
+               /* Note:  V4L2 defines RGB565X as:
+                *
+                *      Byte 0                    Byte 1
+                *      b4 b3 b2 b1 b0 g5 g4 g3   g2 g1 g0 r4 r3 r2 r1 r0
+                *
+                * We interpret RGB565X as:
+                *
+                *      Byte 0                    Byte 1
+                *      r4 r3 r2 r1 r0 g5 g4 g3   g2 g1 g0 b4 b3 b2 b1 b0
+                */
+               .description    = "RGB565, be",
+               .pixelformat    = V4L2_PIX_FMT_RGB565X,
+       },
+       {
+               .description    = "YUYV (YUV 4:2:2), packed",
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+       },{
+               .description    = "UYVY, packed",
+               .pixelformat    = V4L2_PIX_FMT_UYVY,
+       },
+       {
+               /* Note:  V4L2 defines RGB555 as:
+                *
+                *      Byte 0                    Byte 1
+                *      g2 g1 g0 r4 r3 r2 r1 r0   x  b4 b3 b2 b1 b0 g4 g3
+                *
+                * We interpret RGB555 as:
+                *
+                *      Byte 0                    Byte 1
+                *      g2 g1 g0 b4 b3 b2 b1 b0   x  r4 r3 r2 r1 r0 g4 g3
+                */
+               .description    = "RGB555, le",
+               .pixelformat    = V4L2_PIX_FMT_RGB555,
+       },{
+               /* Note:  V4L2 defines RGB555X as:
+                *
+                *      Byte 0                    Byte 1
+                *      x  b4 b3 b2 b1 b0 g4 g3   g2 g1 g0 r4 r3 r2 r1 r0
+                *
+                * We interpret RGB555X as:
+                *
+                *      Byte 0                    Byte 1
+                *      x  r4 r3 r2 r1 r0 g4 g3   g2 g1 g0 b4 b3 b2 b1 b0
+                */
+               .description    = "RGB555, be",
+               .pixelformat    = V4L2_PIX_FMT_RGB555X,
+       }
+};
+
+#define NUM_CAPTURE_FORMATS (sizeof(ov9640_formats)/sizeof(ov9640_formats[0]))
+#define NUM_OVERLAY_FORMATS 2
+
+/* register initialization tables for OV9640 */
+
+#define OV9640_REG_TERM 0xFF   /* terminating list entry for reg */
+#define OV9640_VAL_TERM 0xFF   /* terminating list entry for val */
+
+/* common OV9640 register initialization for all image sizes, pixel formats, 
+ * and frame rates
+ */
+const static struct ov9640_reg ov9640_common[] = {
+       { 0x12, 0x80 }, { 0x11, 0x80 }, { 0x13, 0x88 }, /* COM7, CLKRC, COM8 */
+       { 0x01, 0x58 }, { 0x02, 0x24 }, { 0x04, 0x00 }, /* BLUE, RED, COM1 */
+       { 0x0E, 0x81 }, { 0x0F, 0x4F }, { 0x14, 0xcA }, /* COM5, COM6, COM9 */
+       { 0x16, 0x02 }, { 0x1B, 0x01 }, { 0x24, 0x70 }, /* ?, PSHFT, AEW */
+       { 0x25, 0x68 }, { 0x26, 0xD3 }, { 0x27, 0x90 }, /* AEB, VPT, BBIAS */
+       { 0x2A, 0x00 }, { 0x2B, 0x00 }, { 0x32, 0x24 }, /* EXHCH, EXHCL, HREF */
+       { 0x33, 0x02 }, { 0x37, 0x02 }, { 0x38, 0x13 }, /* CHLF, ADC, ACOM */
+       { 0x39, 0xF0 }, { 0x3A, 0x00 }, { 0x3B, 0x01 }, /* OFON, TSLB, COM11 */
+       { 0x3D, 0x90 }, { 0x3E, 0x02 }, { 0x3F, 0xF2 }, /* COM13, COM14, EDGE */
+       { 0x41, 0x02 }, { 0x42, 0xC8 },         /* COM16, COM17 */
+       { 0x43, 0xF0 }, { 0x44, 0x10 }, { 0x45, 0x6C }, /* ?, ?, ? */
+       { 0x46, 0x6C }, { 0x47, 0x44 }, { 0x48, 0x44 }, /* ?, ?, ? */
+       { 0x49, 0x03 }, { 0x59, 0x49 }, { 0x5A, 0x94 }, /* ?, ?, ? */
+       { 0x5B, 0x46 }, { 0x5C, 0x84 }, { 0x5D, 0x5C }, /* ?, ?, ? */
+       { 0x5E, 0x08 }, { 0x5F, 0x00 }, { 0x60, 0x14 }, /* ?, ?, ? */
+       { 0x61, 0xCE },                                 /* ? */
+       { 0x62, 0x70 }, { 0x63, 0x00 }, { 0x64, 0x04 }, /* LCC1, LCC2, LCC3 */
+       { 0x65, 0x00 }, { 0x66, 0x00 },                 /* LCC4, LCC5 */
+       { 0x69, 0x00 }, { 0x6A, 0x3E }, { 0x6B, 0x3F }, /* HV, MBD, DBLV */
+       { 0x6C, 0x40 }, { 0x6D, 0x30 }, { 0x6E, 0x4B }, /* GSP1, GSP2, GSP3 */
+       { 0x6F, 0x60 }, { 0x70, 0x70 }, { 0x71, 0x70 }, /* GSP4, GSP5, GSP6 */
+       { 0x72, 0x70 }, { 0x73, 0x70 }, { 0x74, 0x60 }, /* GSP7, GSP8, GSP9 */
+       { 0x75, 0x60 }, { 0x76, 0x50 }, { 0x77, 0x48 }, /* GSP10,GSP11,GSP12 */
+       { 0x78, 0x3A }, { 0x79, 0x2E }, { 0x7A, 0x28 }, /* GSP13,GSP14,GSP15 */
+       { 0x7B, 0x22 }, { 0x7C, 0x04 }, { 0x7D, 0x07 }, /* GSP16,GST1, GST2 */
+       { 0x7E, 0x10 }, { 0x7F, 0x28 }, { 0x80, 0x36 }, /* GST3, GST4, GST5 */
+       { 0x81, 0x44 }, { 0x82, 0x52 }, { 0x83, 0x60 }, /* GST6, GST7, GST8 */
+       { 0x84, 0x6C }, { 0x85, 0x78 }, { 0x86, 0x8C }, /* GST9, GST10,GST11 */
+       { 0x87, 0x9E }, { 0x88, 0xBB }, { 0x89, 0xD2 }, /* GST12,GST13,GST14 */
+       { 0x8A, 0xE6 }, { 0x13, 0xaF }, { 0x15, 0x02 }, /* GST15, COM8 */
+       { 0x22, 0x8a }, /* GROS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+
+/* OV9640 register configuration for all combinations of pixel format and 
+ * image size
+ */
+       /* YUV (YCbCr) QQCIF */
+const static struct ov9640_reg qqcif_yuv[] = {
+       { 0x12, 0x08 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x24 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x0F },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* YUV (YCbCr) QQVGA */
+const static struct ov9640_reg qqvga_yuv[] = {
+       { 0x12, 0x10 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x24 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x0F },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* YUV (YCbCr) QCIF */
+const static struct ov9640_reg qcif_yuv[] = {
+       { 0x12, 0x08 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x0F },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* YUV (YCbCr) QVGA */
+const static struct ov9640_reg qvga_yuv[] = {
+       { 0x12, 0x10 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x0F },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* YUV (YCbCr) CIF */
+const static struct ov9640_reg cif_yuv[] = {
+       { 0x12, 0x20 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x0F },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* YUV (YCbCr) VGA */
+const static struct ov9640_reg vga_yuv[] = {
+       { 0x12, 0x40 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x0F },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* YUV (YCbCr) SXGA */
+const static struct ov9640_reg sxga_yuv[] = {
+       { 0x12, 0x00 }, { 0x3C, 0x46 }, { 0x40, 0xC0 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x50 }, { 0x50, 0x43 }, { 0x51, 0x0D }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x19 }, { 0x53, 0x4C }, { 0x54, 0x65 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x40 }, { 0x56, 0x40 }, { 0x57, 0x40 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x0F },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB565 QQCIF */
+const static struct ov9640_reg qqcif_565[] = {
+       { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x24 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB565 QQVGA */
+const static struct ov9640_reg qqvga_565[] = {
+       { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x24 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB565 QCIF */
+const static struct ov9640_reg qcif_565[] = {
+       { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB565 QVGA */
+const static struct ov9640_reg qvga_565[] = {
+       { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB565 CIF */
+const static struct ov9640_reg cif_565[] = {
+       { 0x12, 0x24 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB565 VGA */
+const static struct ov9640_reg vga_565[] = {
+       { 0x12, 0x44 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB565 SXGA */
+const static struct ov9640_reg sxga_565[] = {
+       { 0x12, 0x04 }, { 0x3C, 0x40 }, { 0x40, 0x10 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB555 QQCIF */
+const static struct ov9640_reg qqcif_555[] = {
+       { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x24 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB555 QQVGA */
+const static struct ov9640_reg qqvga_555[] = {
+       { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x24 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB555 QCIF */
+const static struct ov9640_reg qcif_555[] = {
+       { 0x12, 0x0C }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB555 QVGA */
+const static struct ov9640_reg qvga_555[] = {
+       { 0x12, 0x14 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB555 CIF */
+const static struct ov9640_reg cif_555[] = {
+       { 0x12, 0x24 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB555 VGA */
+const static struct ov9640_reg vga_555[] = {
+       { 0x12, 0x44 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x04 }, { 0x0D, 0xC0 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+       /* RGB555 SXGA */
+const static struct ov9640_reg sxga_555[] = {
+       { 0x12, 0x04 }, { 0x3C, 0x40 }, { 0x40, 0x30 }, /* COM7, COM12, COM15 */
+       { 0x04, 0x00 }, { 0x0C, 0x00 }, { 0x0D, 0x40 }, /* COM1, COM3, COM4 */
+       { 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C }, /* MTX1, MTX2, MTX3 */
+       { 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 }, /* MTX4, MTX5, MTX6 */
+       { 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 }, /* MTX7, MTX8, MTX9 */
+       { 0x58, 0x65 },                                 /* MTXS */
+       { OV9640_REG_TERM, OV9640_VAL_TERM }
+};
+
+#define DEF_GAIN         31
+#define DEF_AUTOGAIN      1
+#define DEF_EXPOSURE    154
+#define DEF_AEC           1
+#define DEF_FREEZE_AGCAEC 0
+#define DEF_BLUE        153
+#define DEF_RED         (255 - DEF_BLUE)
+#define DEF_AWB           1
+#define DEF_HFLIP         0
+#define DEF_VFLIP         0
+
+/* Our own specific controls */
+#define V4L2_CID_FREEZE_AGCAEC V4L2_CID_PRIVATE_BASE+0
+#define V4L2_CID_AUTOEXPOSURE V4L2_CID_PRIVATE_BASE+1
+#define V4L2_CID_LAST_PRIV  V4L2_CID_AUTOEXPOSURE
+
+/*  Video controls  */
+static struct vcontrol {
+        struct v4l2_queryctrl qc;
+        int current_value;
+        u8 reg;
+        u8 mask;
+        u8 start_bit;
+} control[] = {
+        { { V4L2_CID_GAIN, V4L2_CTRL_TYPE_INTEGER, "Gain", 0, 63, 1,
+            DEF_GAIN },
+          0, OV9640_GAIN, 0x3f, 0 },
+        { { V4L2_CID_AUTOGAIN, V4L2_CTRL_TYPE_BOOLEAN, "Auto Gain", 0, 1, 0,
+            DEF_AUTOGAIN },
+          0, OV9640_COM8, 0x04, 2 },
+        { { V4L2_CID_EXPOSURE, V4L2_CTRL_TYPE_INTEGER, "Exposure", 0, 255, 1,
+            DEF_EXPOSURE },
+          0, OV9640_AECH, 0xff, 0 },
+        { { V4L2_CID_AUTOEXPOSURE, V4L2_CTRL_TYPE_BOOLEAN, "Auto Exposure", 0, 1, 0,
+            DEF_AEC },
+          0, OV9640_COM8, 0x01, 0 },
+        { { V4L2_CID_FREEZE_AGCAEC, V4L2_CTRL_TYPE_BOOLEAN, "Freeze AGC/AEC", 0,1,0,
+            DEF_FREEZE_AGCAEC },
+          0, OV9640_COM9, 0x01, 0 },
+        { { V4L2_CID_RED_BALANCE, V4L2_CTRL_TYPE_INTEGER, "Red Balance", 0, 255, 1,
+            DEF_RED },
+          0, OV9640_RED, 0xff, 0 },
+        { { V4L2_CID_BLUE_BALANCE, V4L2_CTRL_TYPE_INTEGER, "Blue Balance", 0, 255, 1,
+            DEF_BLUE },
+          0, OV9640_BLUE, 0xff, 0 },
+        { { V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CTRL_TYPE_BOOLEAN, "Auto White Balance", 0,1,0,
+            DEF_AWB },
+          0, OV9640_COM8, 0x02, 1 },
+        { { V4L2_CID_HFLIP, V4L2_CTRL_TYPE_BOOLEAN, "Mirror Image", 0, 1, 0,
+            DEF_HFLIP },
+          0, OV9640_MVFP, 0x20, 5 },
+        { { V4L2_CID_VFLIP, V4L2_CTRL_TYPE_BOOLEAN, "Vertical Flip", 0, 1, 0,
+            DEF_VFLIP },
+          0, OV9640_MVFP, 0x10, 4 },
+};
+
+#define NUM_CONTROLS (sizeof(control)/sizeof(control[0]))
+
+const static struct ov9640_reg *
+       ov9640_reg_init[NUM_PIXEL_FORMATS][NUM_IMAGE_SIZES] =
+{
+ { qqcif_yuv, qqvga_yuv, qcif_yuv, qvga_yuv, cif_yuv, vga_yuv, sxga_yuv },
+ { qqcif_565, qqvga_565, qcif_565, qvga_565, cif_565, vga_565, sxga_565 },
+ { qqcif_555, qqvga_555, qcif_555, qvga_555, cif_555, vga_555, sxga_555 },
+};
+
+
+/* 
+ * Read a value from a register in an OV9640 sensor device.  The value is 
+ * returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int 
+ov9640_read_reg(struct i2c_client *client, u8 reg, u8 *val)
+{
+       int err;
+       struct i2c_msg msg[1];
+       unsigned char data[1];
+
+       if (!client->adapter)
+               return -ENODEV;
+
+       msg->addr = client->addr;
+       msg->flags = 0;
+       msg->len = 1;
+       msg->buf = data;
+       *data = reg;
+       err = i2c_transfer(client->adapter, msg, 1);
+       if (err >= 0) {
+               msg->flags = I2C_M_RD;
+               err = i2c_transfer(client->adapter, msg, 1);
+       }
+       if (err >= 0) {
+               *val = *data;
+               return 0;
+       }
+       return err;
+}
+
+/* Write a value to a register in an OV9640 sensor device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int 
+ov9640_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+       int err;
+       struct i2c_msg msg[1];
+       unsigned char data[2];
+
+       if (!client->adapter)
+               return -ENODEV;
+       
+       msg->addr = client->addr;
+       msg->flags = 0;
+       msg->len = 2;
+       msg->buf = data;
+       data[0] = reg;
+       data[1] = val;
+       err = i2c_transfer(client->adapter, msg, 1);
+       if (err >= 0)
+               return 0;
+       return err;
+}
+
+static int 
+ov9640_write_reg_mask(struct i2c_client *client, u8 reg, u8 *val, u8 mask)
+{
+       u8 oldval, newval;
+       int rc;
+
+       if (mask == 0xff) {
+               newval = *val;
+       } else {
+               /* need to do read - modify - write */
+               if ((rc = ov9640_read_reg(client, reg, &oldval)))
+                       return rc;
+               oldval &= (~mask);              /* Clear the masked bits */
+               *val &= mask;                  /* Enforce mask on value */
+               newval = oldval | *val;        /* Set the desired bits */
+       }
+
+       /* write the new value to the register */
+       if ((rc = ov9640_write_reg(client, reg, newval)))
+               return rc;
+
+       if ((rc = ov9640_read_reg(client, reg, &newval)))
+               return rc;
+
+       *val = newval & mask;
+       return 0;
+}
+
+static int 
+ov9640_read_reg_mask(struct i2c_client *client, u8 reg, u8 *val, u8 mask)
+{
+       int rc;
+
+       if ((rc = ov9640_read_reg(client, reg, val)))
+               return rc;
+       (*val) &= mask;
+
+       return 0;
+}
+
+/* Initialize a list of OV9640 registers.
+ * The list of registers is terminated by the pair of values 
+ * { OV9640_REG_TERM, OV9640_VAL_TERM }.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int 
+ov9640_write_regs(struct i2c_client *client, const struct ov9640_reg reglist[])
+{
+       int err;
+       const struct ov9640_reg *next = reglist;
+       
+       while (!((next->reg == OV9640_REG_TERM) 
+               && (next->val == OV9640_VAL_TERM)))
+       {
+               err = ov9640_write_reg(client, next->reg, next->val);
+               udelay(100);
+               if (err)
+                       return err;
+               next++;
+       }
+       return 0;
+}
+
+/* Returns the index of the requested ID from the control structure array */
+static int
+find_vctrl(int id)
+{
+       int i;
+
+       if (id < V4L2_CID_BASE)
+               return -EDOM;
+
+       for (i = NUM_CONTROLS - 1; i >= 0; i--)
+               if (control[i].qc.id == id)
+                       break;
+       if (i < 0)
+               i = -EINVAL;
+       return i;
+}
+
+/* Calculate the internal clock divisor (value of the CLKRC register) of the 
+ * OV9640 given the image size, the frequency (in Hz) of its XCLK input and a 
+ * desired frame period (in seconds).  The frame period 'fper' is expressed as 
+ * a fraction.  The frame period is an input/output parameter.
+ * Returns the value of the OV9640 CLKRC register that will yield the frame 
+ * period returned in 'fper' at the specified xclk frequency.  The 
+ * returned period will be as close to the requested period as possible.
+ */
+static unsigned char
+ov9640_clkrc(enum image_size isize, unsigned long xclk, struct v4l2_fract *fper)
+{
+       unsigned long fpm, fpm_max;     /* frames per minute */
+       unsigned long divisor;
+       const unsigned long divisor_max = 64;
+       const static unsigned long clks_per_frame[] = 
+               { 200000, 200000, 200000, 200000, 400000, 800000, 3200000 };
+
+       if (fper->numerator > 0)
+               fpm = (fper->denominator*60)/fper->numerator;
+       else
+               fpm = 0xffffffff;
+       fpm_max = (xclk*60)/clks_per_frame[isize];
+       if (fpm_max == 0)
+               fpm_max = 1;
+       if (fpm > fpm_max)
+               fpm = fpm_max;
+       if (fpm == 0)
+               fpm = 1;
+       divisor = fpm_max/fpm;
+       if (divisor > divisor_max)
+               divisor = divisor_max;
+       fper->numerator = divisor*60;
+       fper->denominator = fpm_max;
+
+       /* try to reduce the fraction */
+       while (!(fper->denominator % 5) && !(fper->numerator % 5)) {
+               fper->numerator /= 5;
+               fper->denominator /= 5;
+       }
+       while (!(fper->denominator % 3) && !(fper->numerator % 3)) {
+               fper->numerator /= 3;
+               fper->denominator /= 3;
+       }
+       while (!(fper->denominator % 2) && !(fper->numerator % 2)) {
+               fper->numerator /= 2;
+               fper->denominator /= 2;
+       }
+       if (fper->numerator < fper->denominator) {
+               if (!(fper->denominator % fper->numerator)) {
+                       fper->denominator /= fper->numerator;
+                       fper->numerator = 1;
+               }
+       }
+       else {
+               if (!(fper->numerator % fper->denominator)) {
+                       fper->numerator /= fper->denominator;
+                       fper->denominator = 1;
+               }
+       }
+
+       /* we set bit 7 in CLKRC to enable the digital PLL */
+       return (0x80 | (divisor - 1));
+}
+
+/* Configure the OV9640 for a specified image size, pixel format, and frame 
+ * period.  xclk is the frequency (in Hz) of the xclk input to the OV9640.  
+ * fper is the frame period (in seconds) expressed as a fraction.
+ * Returns zero if successful, or non-zero otherwise.
+ * The actual frame period is returned in fper.
+ */
+static int
+ov9640_configure(struct i2c_client *client, 
+       enum image_size isize, 
+       enum pixel_format pfmt,
+       unsigned long xclk,
+       struct v4l2_fract *fper)
+{
+       int err;
+       unsigned char clkrc;
+
+       /* common register initialization */
+       err = ov9640_write_regs(client, ov9640_common);
+       if (err)
+               return err;
+
+       /* configure image size and pixel format */
+       err = ov9640_write_regs(client, ov9640_reg_init[pfmt][isize]);
+       if (err)
+               return err;
+
+       /* configure frame rate */
+       clkrc = ov9640_clkrc(isize, xclk, fper);
+       err = ov9640_write_reg(client, OV9640_CLKRC, clkrc);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+static int
+ov9640_powerup(void)
+{
+       unsigned char expa;
+       int err;
+
+       if (machine_is_omap_h2())
+               return 0;
+
+       /* read the current state of GPIO EXPA output */
+       if (( err = read_gpio_expa(&expa, 0x27))){
+               printk(KERN_ERR "Error reading GPIO EXPA \n");
+               return err;
+       }
+       /* set GPIO EXPA P7 CAMERA_MOD_EN to power-up sensor */
+       if ((err = write_gpio_expa(expa | 0x80, 0x27))) {
+               printk(KERN_ERR "Error writing to GPIO EXPA \n");
+               return err;
+       }
+
+       return 0;
+}
+static int
+ov9640_powerdown(void)
+{
+       unsigned char expa;
+       int err;
+
+       if (machine_is_omap_h2())
+               return 0;
+
+       /* read the current state of GPIO EXPA output */
+       if (( err = read_gpio_expa(&expa, 0x27))){
+               printk(KERN_ERR "Error reading GPIO EXPA \n");
+               return err;
+       }
+       /* clear GPIO EXPA P7 CAMERA_MOD_EN to power-up sensor */
+       if ((err = write_gpio_expa(expa & ~0x80, 0x27))) {
+               printk(KERN_ERR "Error writing to GPIO EXPA \n");
+               return err;
+       }
+       return 0;
+}
+
+static int
+ov9640sensor_power_on(void *priv)
+{
+       return ov9640_powerup();
+}
+
+static int
+ov9640sensor_power_off(void *priv)
+{
+       return ov9640_powerdown();
+}
+
+/* Detect if an OV9640 is present, and if so which revision. 
+ * A device is considered to be detected if the manufacturer ID (MIDH and MIDL) 
+ * and the product ID (PID) registers match the expected values.  
+ * Any value of the version ID (VER) register is accepted.
+ * Here are the version numbers we know about:
+ *     0x48 --> OV9640 Revision 1 or OV9640 Revision 2
+ *     0x49 --> OV9640 Revision 3
+ * Returns a negative error number if no device is detected, or the 
+ * non-negative value of the version ID register if a device is detected.
+ */
+static int
+ov9640_detect(struct i2c_client *client)
+{
+       u8 midh, midl, pid, ver;
+
+       if (!client)
+               return -ENODEV;
+       if (ov9640_read_reg(client, OV9640_MIDH, &midh))
+               return -ENODEV;
+       if (ov9640_read_reg(client, OV9640_MIDL, &midl))
+               return -ENODEV;
+       if (ov9640_read_reg(client, OV9640_PID, &pid))
+               return -ENODEV;
+       if (ov9640_read_reg(client, OV9640_VER, &ver))
+               return -ENODEV;
+
+       if ((midh != OV9640_MIDH_MAGIC) 
+               || (midl != OV9640_MIDL_MAGIC)
+               || (pid != OV9640_PID_MAGIC))
+       {
+               /* We didn't read the values we expected, so 
+                * this must not be an OV9640.
+                */
+               return -ENODEV;
+       }
+       return ver;
+}
+
+/* This function registers an I2C client via i2c_attach_client() for an OV9640 
+ * sensor device.  If 'probe' is non-zero, then the I2C client is only 
+ * registered if the device can be detected.  If 'probe' is zero, then no 
+ * device detection is attempted and the I2C client is always registered.
+ * Returns zero if an I2C client is successfully registered, or non-zero 
+ * otherwise.
+ */
+static int 
+ov9640_i2c_attach_client(struct i2c_adapter *adap, int addr, int probe)
+{
+       struct ov9640_sensor *sensor = &ov9640;
+       struct i2c_client *client = &sensor->client;
+       int err;
+
+       if (client->adapter)
+               return -EBUSY;  /* our client is already attached */
+
+       client->addr = addr;
+       client->flags = I2C_CLIENT_ALLOW_USE;
+       client->driver = &sensor->driver;
+       client->adapter = adap;
+
+       err = i2c_attach_client(client);
+       if (err) {
+               client->adapter = NULL;
+               return err;
+       }
+
+       if (probe) {
+               err = ov9640_detect(client);
+               if (err < 0) {
+                       i2c_detach_client(client);
+                       client->adapter = NULL;
+                       return err;
+               }
+               sensor->ver = err;
+       }
+       return 0;
+}
+
+/* This function is called by i2c_del_adapter() and i2c_del_driver() 
+ * if the adapter or driver with which this I2C client is associated is 
+ * removed.  This function unregisters the client via i2c_detach_client().
+ * Returns zero if the client is successfully detached, or non-zero 
+ * otherwise.
+ */
+static int 
+ov9640_i2c_detach_client(struct i2c_client *client)
+{
+       int err;
+
+       if (!client->adapter)
+               return -ENODEV; /* our client isn't attached */
+
+       err = i2c_detach_client(client);
+       client->adapter = NULL;
+
+       return err;
+}
+
+/* This function will be called for each registered I2C bus adapter when our 
+ * I2C driver is registered via i2c_add_driver().  It will also be called 
+ * whenever a new I2C adapter is registered after our I2C driver is registered.
+ * This function probes the specified I2C bus adapter to determine if an 
+ * OV9640 sensor device is present.  If a device is detected, an I2C client 
+ * is registered for it via ov9640_i2c_attach_client().  Note that we can't use 
+ * the standard i2c_probe() function to look for the sensor because the OMAP 
+ * I2C controller doesn't support probing.
+ * Returns zero if an OV9640 device is detected and an I2C client successfully 
+ * registered for it, or non-zero otherwise.
+ */
+static int 
+ov9640_i2c_probe_adapter(struct i2c_adapter *adap)
+{
+       return ov9640_i2c_attach_client(adap, OV9640_I2C_ADDR, 1);
+}
+
+/* Find the best match for a requested image capture size.  The best match 
+ * is chosen as the nearest match that has the same number or fewer pixels 
+ * as the requested size, or the smallest image size if the requested size 
+ * has fewer pixels than the smallest image.
+ */
+static enum image_size
+ov9640_find_size(unsigned int width, unsigned int height)
+{
+       enum image_size isize;
+       unsigned long pixels = width*height;
+
+       for (isize = QQCIF; isize < SXGA; isize++) {
+               if (ov9640_sizes[isize + 1].height*
+                       ov9640_sizes[isize + 1].width > pixels)
+               {
+                       return isize;
+               }
+       }
+       return SXGA;
+}
+
+/* following are sensor interface functions implemented by 
+ * OV9640 sensor driver.
+ */
+static int
+ov9640sensor_query_control(struct v4l2_queryctrl *qc, void *priv)
+{
+       int i;
+
+       i = find_vctrl (qc->id);
+       if (i == -EINVAL) {
+               qc->flags = V4L2_CTRL_FLAG_DISABLED;
+               return 0;
+       }
+       if (i < 0)
+               return -EINVAL;
+
+       *qc = control[i].qc;
+       return 0;
+}
+
+static int
+ov9640sensor_get_control(struct v4l2_control *vc, void *priv)
+{
+       struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
+       struct i2c_client *client = &sensor->client;
+       int i, val;
+       struct vcontrol * lvc;
+       
+       i = find_vctrl(vc->id);
+       if (i < 0)
+               return -EINVAL;
+
+       lvc = &control[i];      
+       if (ov9640_read_reg_mask(client, lvc->reg, (u8 *)&val, lvc->mask))
+               return -EIO;
+               
+       val = val >> lvc->start_bit;    
+       if (val >= 0) {
+               vc->value = lvc->current_value = val;
+               return 0;
+       } else
+               return val;
+}
+
+static int
+ov9640sensor_set_control(struct v4l2_control *vc, void *priv)
+{
+       struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
+       struct i2c_client *client = &sensor->client;
+       struct vcontrol *lvc;
+       int val = vc->value;
+       int i;
+
+       i = find_vctrl(vc->id);
+       if (i < 0)
+               return -EINVAL;
+
+       lvc = &control[i];
+       val = val << lvc->start_bit;
+       if (ov9640_write_reg_mask(client, lvc->reg, (u8 *)&val, (u8)lvc->mask))
+               return -EIO;
+
+       val = val>> lvc->start_bit;
+       if (val >= 0) {
+               lvc->current_value = val;
+               return 0;
+       } else
+               return val;
+}
+
+/* Implement the VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
+ */
+static int
+ov9640sensor_enum_pixformat(struct v4l2_fmtdesc *fmt, void *priv)
+{
+       int index = fmt->index;
+       enum v4l2_buf_type type = fmt->type;
+
+       memset(fmt, 0, sizeof(*fmt));
+       fmt->index = index;
+       fmt->type = type;
+
+       switch (fmt->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if (index >= NUM_CAPTURE_FORMATS)
+                       return -EINVAL;
+               break;
+
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               if (index >= NUM_OVERLAY_FORMATS)
+                       return -EINVAL;
+               break;
+
+               default:
+                       return -EINVAL;
+       }
+
+       fmt->flags = ov9640_formats[index].flags;
+       strlcpy(fmt->description, ov9640_formats[index].description, sizeof(fmt->description));
+       fmt->pixelformat = ov9640_formats[index].pixelformat;
+
+       return 0;
+}
+
+/* Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.  This 
+ * ioctl is used to negotiate the image capture size and pixel format 
+ * without actually making it take effect.
+ */
+static int
+ov9640sensor_try_format(struct v4l2_pix_format *pix, void *priv)
+{
+       enum image_size isize;
+       int ifmt;
+
+       isize = ov9640_find_size(pix->width, pix->height);
+       pix->width = ov9640_sizes[isize].width;
+       pix->height = ov9640_sizes[isize].height;
+       for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
+               if (pix->pixelformat == ov9640_formats[ifmt].pixelformat)
+                       break;
+       }
+       if (ifmt == NUM_CAPTURE_FORMATS)
+               ifmt = 0;
+       pix->pixelformat = ov9640_formats[ifmt].pixelformat;
+       pix->field = V4L2_FIELD_NONE;
+       pix->bytesperline = pix->width*2;
+       pix->sizeimage = pix->bytesperline*pix->height;
+       pix->priv = 0;
+       switch (pix->pixelformat) {
+               case V4L2_PIX_FMT_YUYV:
+               case V4L2_PIX_FMT_UYVY:
+               default:
+                       pix->colorspace = V4L2_COLORSPACE_JPEG;
+                       break;
+               case V4L2_PIX_FMT_RGB565:
+               case V4L2_PIX_FMT_RGB565X:
+               case V4L2_PIX_FMT_RGB555:
+               case V4L2_PIX_FMT_RGB555X:
+                       pix->colorspace = V4L2_COLORSPACE_SRGB;
+                       break;
+       }
+       return 0;
+}
+
+/* Given the image capture format in pix, the nominal frame period in 
+ * timeperframe, calculate the required xclk frequency 
+ * The nominal xclk input frequency of the OV9640 is 24MHz, maximum 
+ * frequency is 48MHz, and minimum frequency is 10MHz.
+ */
+static unsigned long
+ov9640sensor_calc_xclk(struct v4l2_pix_format *pix,
+                       struct v4l2_fract *timeperframe, void *priv)
+{
+       unsigned long tgt_xclk;                 /* target xclk */
+       unsigned long tgt_fpm;                  /* target frames per minute */
+       enum image_size isize;
+
+       /* We use arbitrary rules to select the xclk frequency.  If the 
+        * capture size is VGA and the frame rate is greater than 900 
+        * frames per minute, or if the capture size is SXGA and the 
+        * frame rate is greater than 450 frames per minutes, then the 
+        * xclk frequency will be set to 48MHz.  Otherwise, the xclk 
+        * frequency will be set to 24MHz.  If the mclk frequency is such that 
+        * the target xclk frequency is not achievable, then xclk will be set 
+        * as close as to the target as possible.
+        */
+       if ((timeperframe->numerator == 0) 
+               || (timeperframe->denominator == 0))
+       {
+               /* supply a default nominal_timeperframe of 15 fps */
+               timeperframe->numerator = 1;
+               timeperframe->denominator = 15;
+       }
+       tgt_fpm = (timeperframe->denominator*60)
+               / timeperframe->numerator;
+       tgt_xclk = 24000000;
+       isize = ov9640_find_size(pix->width, pix->height);
+       switch (isize) {
+               case SXGA:
+                       if (tgt_fpm > 450)
+                               tgt_xclk = 48000000;
+                       break;
+               case VGA:
+                       if (tgt_fpm > 900)
+                               tgt_xclk = 48000000;
+                       break;
+               default:
+                       break;
+       }
+       return tgt_xclk;
+}
+
+/* Given a capture format in pix, the frame period in timeperframe, and
+ * the xclk frequency, set the capture format of the OV9640 sensor.
+ * The actual frame period will be returned in timeperframe.
+ */
+static int
+ov9640sensor_configure(struct v4l2_pix_format *pix, unsigned long xclk,
+                       struct v4l2_fract *timeperframe, void *priv)
+{
+       struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
+       enum pixel_format pfmt = YUV;
+
+       switch (pix->pixelformat) {
+               case V4L2_PIX_FMT_RGB565:
+               case V4L2_PIX_FMT_RGB565X:
+                       pfmt = RGB565;
+                       break;
+               case V4L2_PIX_FMT_RGB555:
+               case V4L2_PIX_FMT_RGB555X:
+                       pfmt = RGB555;
+                       break;
+               case V4L2_PIX_FMT_YUYV:
+               case V4L2_PIX_FMT_UYVY:
+               default:
+                       pfmt = YUV;
+       }
+
+       return ov9640_configure(&sensor->client,
+                               ov9640_find_size(pix->width, pix->height),
+                               pfmt, xclk, timeperframe);
+}
+
+/* Prepare for the driver to exit.
+ * Balances ov9640sensor_init().
+ * This function must de-initialize the sensor and its associated data 
+ * structures.
+ */
+static int
+ov9640sensor_cleanup(void *priv)
+{
+       struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
+
+       if (sensor) {
+               i2c_del_driver(&sensor->driver);
+               ov9640_powerdown();
+       }
+       return 0;
+}
+
+/* Initialize the OV9640 sensor.
+ * This routine allocates and initializes the data structure for the sensor, 
+ * powers up the sensor, registers the I2C driver, and sets a default image 
+ * capture format in pix.  The capture format is not actually programmed 
+ * into the OV9640 sensor by this routine.
+ * This function must return a non-NULL value to indicate that 
+ * initialization is successful.
+ */
+static void *
+ov9640sensor_init(struct v4l2_pix_format *pix)
+{
+       struct ov9640_sensor *sensor = &ov9640;
+       struct i2c_driver *driver = &sensor->driver;
+       int err;
+
+       memset(sensor, 0, sizeof(*sensor));
+       /* power-up the sensor */
+       if (ov9640_powerup())
+               return NULL;
+
+       driver->owner = THIS_MODULE;
+       strlcpy(driver->name, "OV9640 I2C driver", sizeof(driver->name));
+       driver->id = I2C_DRIVERID_EXP0;
+       driver->flags = I2C_DF_NOTIFY;
+       driver->attach_adapter = ov9640_i2c_probe_adapter;
+       driver->detach_client = ov9640_i2c_detach_client;
+
+       err = i2c_add_driver(driver);
+       if (err) {
+               printk(KERN_ERR "Failed to register OV9640 I2C client.\n");
+               return NULL;
+       }
+       if (!sensor->client.adapter) {
+               printk(KERN_WARNING 
+                       "Failed to detect OV9640 sensor chip.\n");
+               return NULL;
+       }
+       else {
+               printk(KERN_INFO 
+                       "OV9640 sensor chip version 0x%02x detected\n", sensor->ver);
+       }
+
+       /* Make the default capture format QCIF RGB565 */
+       pix->width = ov9640_sizes[QCIF].width;
+       pix->height = ov9640_sizes[QCIF].height;
+       pix->pixelformat = V4L2_PIX_FMT_RGB565;
+       ov9640sensor_try_format(pix, NULL);
+
+       return (void *)sensor;
+}
+
+struct camera_sensor camera_sensor_if = {
+       version:        0x01,
+       name:           "OV9640",
+       init:           ov9640sensor_init,
+       cleanup:        ov9640sensor_cleanup, 
+       enum_pixformat: ov9640sensor_enum_pixformat,
+       try_format:     ov9640sensor_try_format,
+       calc_xclk:      ov9640sensor_calc_xclk,
+       configure:      ov9640sensor_configure,
+       query_control:  ov9640sensor_query_control, 
+       get_control:    ov9640sensor_get_control, 
+       set_control:    ov9640sensor_set_control,
+       power_on:       ov9640sensor_power_on,
+       power_off:      ov9640sensor_power_off,
+};
+
+void print_ov9640_regs(void *priv)
+{
+       struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;
+       u8 reg, val;
+       for (reg=0x00; reg <=0x8A; reg++)
+               if (ov9640_read_reg(&sensor->client,reg,&val))
+                       printk("error reading %x\n", reg);
+               else
+                       printk("reg %x = %x\n", reg, val);       
+}
+
+#endif /* ifdef CAMERA_OV9640 */
index c483a863b116fd6afecdfeb9372520d4987b744a..94b5073b7412ed2c6b0491ed152b14defffdcc43 100644 (file)
@@ -29,6 +29,23 @@ config MMC_BLOCK
          mount the filesystem. Almost everyone wishing MMC support
          should say Y or M here.
 
+config MMC_BLOCK_BROKEN_RFD
+       boolean "Write work-around for incompatible cards"
+       depends on MMC_BLOCK
+       default n
+       help
+         Say y here if your MMC card fails write operations. Some cards
+         lie about being ready to receive data while they actually are not.
+
+config MMC_BULKTRANSFER
+       bool "Multi-block writes (EXPERIMENTAL)"
+       depends on MMC_BLOCK != n && EXPERIMENTAL
+       default n
+       help
+         By default all writes are done one sector at a time. Enable
+         this option to transfer as large blocks as the host supports.
+         The transfer speed is in most cases doubled.
+
 config MMC_ARMMMCI
        tristate "ARM AMBA Multimedia Card Interface support"
        depends on ARM_AMBA && MMC
@@ -49,6 +66,17 @@ config MMC_PXA
 
          If unsure, say N.
 
+config MMC_OMAP
+       tristate "TI OMAP Multimedia Card Interface support"
+       depends on ARCH_OMAP && MMC
+       select TPS65010 if MACH_OMAP_H2
+       help
+         This selects the TI OMAP Multimedia card Interface.
+         If you have an OMAP board with a Multimedia Card slot,
+         say Y or M here.
+
+         If unsure, say N.
+
 config MMC_WBSD
        tristate "Winbond W83L51xD SD/MMC Card Interface support"
        depends on MMC && ISA_DMA_API
index e351e71146e9073960935f48b44df6761ae3fc17..27cbef71ffc7fd90f95a36197defcf0afccf64a8 100644 (file)
@@ -19,5 +19,6 @@ obj-$(CONFIG_MMC_ARMMMCI)     += mmci.o
 obj-$(CONFIG_MMC_PXA)          += pxamci.o
 obj-$(CONFIG_MMC_WBSD)         += wbsd.o
 obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
+obj-$(CONFIG_MMC_OMAP)         += omap.o
 
 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
index da528390acf87293292237abddf2bf5cf66b600c..10f7a978cb93a1ac2b2cc817a1ff985a07fe36dd 100644 (file)
@@ -686,6 +686,7 @@ static void mmc_power_up(struct mmc_host *host)
        int bit = fls(host->ocr_avail) - 1;
 
        host->ios.vdd = bit;
+       host->ios.clock = host->f_min;
        host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
        host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_UP;
@@ -694,7 +695,6 @@ static void mmc_power_up(struct mmc_host *host)
 
        mmc_delay(1);
 
-       host->ios.clock = host->f_min;
        host->ios.power_mode = MMC_POWER_ON;
        host->ops->set_ios(host, &host->ios);
 
@@ -728,7 +728,7 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
 
                if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
                        break;
-
+               mmc_delay(1);
                err = MMC_ERR_TIMEOUT;
 
                mmc_delay(10);
@@ -1069,6 +1069,14 @@ static void mmc_setup(struct mmc_host *host)
        host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
        host->ops->set_ios(host, &host->ios);
 
+       /*
+        * Some already detectd cards get confused in the card identification
+        * mode and futher commands can fail.  Doing an extra status inquiry
+        * after the identification mode seems to get cards back to their
+        * senses.
+        */
+       mmc_check_cards(host);
+
        mmc_read_csds(host);
 
        if (host->mode == MMC_MODE_SD)
index d91fcf7c3178294fbef7bdfd1394efeb35bb4014..62de54a3d3d91bb1d152741009ae85f687e89f6f 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -54,6 +55,7 @@ struct mmc_blk_data {
 
        unsigned int    usage;
        unsigned int    block_bits;
+       unsigned int    suspended;
 };
 
 static DECLARE_MUTEX(open_lock);
@@ -168,6 +170,19 @@ static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req)
                stat = BLKPREP_KILL;
        }
 
+       if (md->suspended) {
+               blk_plug_device(md->queue.queue);
+               stat = BLKPREP_DEFER;
+       }
+
+       /*
+        * Check for excessive requests.
+        */
+       if (req->sector + req->nr_sectors > get_capacity(req->rq_disk)) {
+               printk("bad request size\n");
+               stat = BLKPREP_KILL;
+       }
+
        return stat;
 }
 
@@ -176,9 +191,25 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        struct mmc_blk_data *md = mq->data;
        struct mmc_card *card = md->queue.card;
        int ret;
+       
+#ifdef CONFIG_MMC_BULKTRANSFER
+       int failsafe;
+#endif
 
        if (mmc_card_claim_host(card))
                goto cmd_err;
+       
+#ifdef CONFIG_MMC_BULKTRANSFER
+       /*
+        * We first try transfering multiple blocks. If this fails
+        * we fall back to single block transfers.
+        *
+        * This gives us good performance when all is well and the
+        * possibility to determine which sector fails when all
+        * is not well.
+        */
+       failsafe = 0;
+#endif
 
        do {
                struct mmc_blk_request brq;
@@ -198,13 +229,32 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                brq.stop.arg = 0;
                brq.stop.flags = MMC_RSP_R1B;
 
+#ifdef CONFIG_MMC_BULKTRANSFER         
+               /*
+                * A multi-block transfer failed. Falling back to single
+                * blocks.
+                */
+               if (failsafe)
+                       brq.data.blocks = 1;
+               
+#else
+               /*
+                * Writes are done one sector at a time.
+                */
+               if (rq_data_dir(req) != READ)
+                       brq.data.blocks = 1;
+#endif
+               
+               ret = 1;
+
                if (rq_data_dir(req) == READ) {
                        brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
                        brq.data.flags |= MMC_DATA_READ;
                } else {
-                       brq.cmd.opcode = MMC_WRITE_BLOCK;
+                       brq.cmd.opcode = brq.data.blocks > 1 ? MMC_WRITE_MULTIPLE_BLOCK :
+                               MMC_WRITE_BLOCK;
+                       brq.cmd.flags = MMC_RSP_R1B;
                        brq.data.flags |= MMC_DATA_WRITE;
-                       brq.data.blocks = 1;
                }
                brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
 
@@ -215,21 +265,25 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                if (brq.cmd.error) {
                        printk(KERN_ERR "%s: error %d sending read/write command\n",
                               req->rq_disk->disk_name, brq.cmd.error);
-                       goto cmd_err;
+                       goto cmd_fail;
                }
 
                if (brq.data.error) {
                        printk(KERN_ERR "%s: error %d transferring data\n",
                               req->rq_disk->disk_name, brq.data.error);
-                       goto cmd_err;
+                       goto cmd_fail;
                }
 
                if (brq.stop.error) {
                        printk(KERN_ERR "%s: error %d sending stop command\n",
                               req->rq_disk->disk_name, brq.stop.error);
-                       goto cmd_err;
+                       goto cmd_fail;
                }
 
+               /* No need to check card status after a read */
+               if (rq_data_dir(req) == READ)
+                       goto card_ready;
+
                do {
                        int err;
 
@@ -240,8 +294,15 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                        if (err) {
                                printk(KERN_ERR "%s: error %d requesting status\n",
                                       req->rq_disk->disk_name, err);
-                               goto cmd_err;
+                               goto cmd_fail;
                        }
+#ifdef CONFIG_MMC_BLOCK_BROKEN_RFD
+                       /* Work-around for broken cards setting READY_FOR_DATA
+                        * when not actually ready.
+                        */
+                       if (R1_CURRENT_STATE(cmd.resp[0]) == 7)
+                               cmd.resp[0] &= ~R1_READY_FOR_DATA;
+#endif
                } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
 
 #if 0
@@ -252,6 +313,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                        goto cmd_err;
 #endif
 
+       card_ready:
+
                /*
                 * A block was successfully transferred.
                 */
@@ -266,6 +329,27 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                        end_that_request_last(req);
                }
                spin_unlock_irq(&md->lock);
+               
+#ifdef CONFIG_MMC_BULKTRANSFER
+               /*
+                * Go back to bulk mode if in failsafe mode.
+                */
+               failsafe = 0;
+#endif
+
+               continue;
+
+ cmd_fail:
+
+#ifdef CONFIG_MMC_BULKTRANSFER
+               if (failsafe)
+                       goto cmd_err;
+               else
+                       failsafe = 1;
+#else
+               goto cmd_err;
+#endif
+
        } while (ret);
 
        mmc_card_release_host(card);
@@ -292,6 +376,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        end_that_request_last(req);
        spin_unlock_irq(&md->lock);
 
+       /* If a command fails, the card might be removed. */
+       mmc_detect_change(card->host, 0);
+
        return 0;
 }
 
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
new file mode 100644 (file)
index 0000000..8294008
--- /dev/null
@@ -0,0 +1,1433 @@
+/*
+ *  linux/drivers/media/mmc/omap.c
+ *
+ *  Copyright (C) 2004 Nokia Corporation
+ *  Written by Tuukka Tikkanen and Juha Yrjölä <juha.yrjola@nokia.com>
+ *  Misc hacks here and there by Tony Lindgren <tony@atomide.com>
+ *  Other hacks (DMA, SD, etc) by David Brownell
+ *
+ * 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>
+
+// #define CONFIG_MMC_DEBUG
+#ifdef CONFIG_MMC_DEBUG
+#define DEBUG  /* for dev_dbg(), pr_debug(), etc */
+#endif
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+#include <linux/mmc/card.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/scatterlist.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/menelaus.h>
+
+#include <asm/hardware/clock.h>
+
+#include "omap.h"
+
+#define DRIVER_NAME "mmci-omap"
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(x...)      pr_debug(x)
+//#define DBG(x...)    printk(x)
+#else
+#define DBG(x...)      do { } while (0)
+#endif
+
+/* Specifies how often in millisecs to poll for card status changes
+ * when the cover switch is open */
+#define OMAP_MMC_SWITCH_POLL_DELAY     500
+
+static int mmc_omap_enable_poll = 1;
+
+struct mmc_omap_host {
+       int                     initialized;
+       int                     suspended;
+       struct mmc_request *    mrq;
+       struct mmc_command *    cmd;
+       struct mmc_data *       data;
+       struct mmc_host *       mmc;
+       struct device *         dev;
+       unsigned char           id; /* 16xx chips have 2 MMC blocks */
+       struct clk *            iclk;
+       struct clk *            fclk;
+       void __iomem            *base;
+       int                     irq;
+       unsigned char           bus_mode;
+       unsigned char           hw_bus_mode;
+
+       unsigned int            sg_len;
+       int                     sg_idx;
+       u16 *                   buffer;
+       u32                     buffer_bytes_left;
+       u32                     total_bytes_left;
+
+       unsigned                use_dma:1;
+       unsigned                brs_received:1, dma_done:1;
+       unsigned                dma_is_read:1;
+       unsigned                dma_in_use:1;
+       int                     dma_ch;
+       spinlock_t              dma_lock;
+       struct timer_list       dma_timer;
+       unsigned                dma_len;
+
+       short                   power_pin;
+       short                   wp_pin;
+
+       int                     switch_pin;
+       struct work_struct      switch_work;
+       struct timer_list       switch_timer;
+       int                     switch_last_state;
+};
+
+static inline int
+mmc_omap_cover_is_open(struct mmc_omap_host *host)
+{
+       if (host->switch_pin < 0)
+               return 0;
+       return omap_get_gpio_datain(host->switch_pin);
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" : "closed");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
+static ssize_t
+mmc_omap_show_enable_poll(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll);
+}
+
+static ssize_t
+mmc_omap_store_enable_poll(struct device *dev,
+       struct device_attribute *attr, const char *buf,
+       size_t size)
+{
+       int enable_poll;
+
+       if (sscanf(buf, "%10d", &enable_poll) != 1)
+               return -EINVAL;
+
+       if (enable_poll != mmc_omap_enable_poll) {
+               struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+               mmc_omap_enable_poll = enable_poll;
+               if (enable_poll && host->switch_pin >= 0)
+                       schedule_work(&host->switch_work);
+       }
+       return size;
+}
+
+static DEVICE_ATTR(enable_poll, 0664,
+                  mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
+
+static void
+mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+       u32 cmdreg;
+       u32 resptype;
+       u32 cmdtype;
+
+       pr_debug("MMC%d: CMD%d, argument 0x%08x%s%s%s%s\n",
+               host->id, cmd->opcode, cmd->arg,
+               (cmd->flags & MMC_RSP_SHORT) ?  ", 32-bit response" : "",
+               (cmd->flags & MMC_RSP_LONG) ?  ", 128-bit response" : "",
+               (cmd->flags & MMC_RSP_CRC) ?  ", CRC" : "",
+               (cmd->flags & MMC_RSP_BUSY) ?  ", busy notification" : "");
+
+       host->cmd = cmd;
+
+       resptype = 0;
+       cmdtype = 0;
+
+       /*
+        * On 24xx we may have external MMC transceiver on Menelaus.
+        * In that case we need to manually toggle between open-drain
+        * and push-pull states.
+        */
+       if (omap_has_menelaus() && (host->bus_mode != host->hw_bus_mode)) {
+               if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+                       menelaus_mmc_opendrain(1);
+               else
+                       menelaus_mmc_opendrain(0);
+               host->hw_bus_mode = host->bus_mode;
+       }
+
+       /* Protocol layer does not provide response type,
+        * but our hardware needs to know exact type, not just size!
+        */
+       switch (cmd->flags & MMC_RSP_MASK) {
+       case MMC_RSP_NONE:
+               /* resp 0 */
+               break;
+       case MMC_RSP_SHORT:
+               /* resp 1, resp 1b */
+               /* OR resp 3!! (assume this if bus is set opendrain) */
+               if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+                       resptype = 3;
+               else
+                       resptype = 1;
+               break;
+       case MMC_RSP_LONG:
+               /* resp 2 */
+               resptype = 2;
+               break;
+       }
+
+       /* Protocol layer does not provide command type, but our hardware
+        * needs it!
+        * any data transfer means adtc type (but that information is not
+        * in command structure, so we flagged it into host struct.)
+        * However, telling bc, bcr and ac apart based on response is
+        * not foolproof:
+        * CMD0  = bc  = resp0  CMD15 = ac  = resp0
+        * CMD2  = bcr = resp2  CMD10 = ac  = resp2
+        *
+        * Resolve to best guess with some exception testing:
+        * resp0 -> bc, except CMD15 = ac
+        * rest are ac, except if opendrain
+        */
+       if (host->data) {
+               cmdtype = OMAP_MMC_CMDTYPE_ADTC;
+       } else if (resptype == 0 && cmd->opcode != 15) {
+               cmdtype = OMAP_MMC_CMDTYPE_BC;
+       } else if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+               cmdtype = OMAP_MMC_CMDTYPE_BCR;
+       } else {
+               cmdtype = OMAP_MMC_CMDTYPE_AC;
+       }
+
+       cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);
+
+       if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+               cmdreg |= 1 << 6;
+
+       if (cmd->flags & MMC_RSP_BUSY)
+               cmdreg |= 1 << 11;
+
+       if (host->data && !(host->data->flags & MMC_DATA_WRITE))
+               cmdreg |= 1 << 15;
+
+       clk_use(host->fclk);
+
+       OMAP_MMC_WRITE(host->base, CTO, 200);
+       OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff);
+       OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16);
+       OMAP_MMC_WRITE(host->base, IE,
+                      OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
+                      OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
+                      OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
+                      OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
+                      OMAP_MMC_STAT_END_OF_DATA);
+       OMAP_MMC_WRITE(host->base, CMD, cmdreg);
+}
+
+static void
+mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       if (host->dma_in_use) {
+               enum dma_data_direction dma_data_dir;
+
+               BUG_ON(host->dma_ch < 0);
+               if (data->error != MMC_ERR_NONE)
+                       omap_stop_dma(host->dma_ch);
+               /* Release DMA channel lazily */
+               mod_timer(&host->dma_timer, jiffies + HZ);
+               if (data->flags & MMC_DATA_WRITE)
+                       dma_data_dir = DMA_TO_DEVICE;
+               else
+                       dma_data_dir = DMA_FROM_DEVICE;
+               dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
+                            dma_data_dir);
+       }
+       host->data = NULL;
+       host->sg_len = 0;
+       clk_unuse(host->fclk);
+
+       /* NOTE:  MMC layer will sometimes poll-wait CMD13 next, issuing
+        * dozens of requests until the card finishes writing data.
+        * It'd be cheaper to just wait till an EOFB interrupt arrives...
+        */
+
+       if (!data->stop) {
+               host->mrq = NULL;
+               mmc_request_done(host->mmc, data->mrq);
+               return;
+       }
+
+       mmc_omap_start_command(host, data->stop);
+}
+
+static void
+mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       unsigned long flags;
+       int done;
+
+       if (!host->dma_in_use) {
+               mmc_omap_xfer_done(host, data);
+               return;
+       }
+       done = 0;
+       spin_lock_irqsave(&host->dma_lock, flags);
+       if (host->dma_done)
+               done = 1;
+       else
+               host->brs_received = 1;
+       spin_unlock_irqrestore(&host->dma_lock, flags);
+       if (done)
+               mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_dma_timer(unsigned long data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+
+       DBG("MMC%d: Freeing DMA channel %d\n", host->id, host->dma_ch);
+       BUG_ON(host->dma_ch < 0);
+       omap_free_dma(host->dma_ch);
+       host->dma_ch = -1;
+}
+
+static void
+mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       unsigned long flags;
+       int done;
+
+       done = 0;
+       spin_lock_irqsave(&host->dma_lock, flags);
+       if (host->brs_received)
+               done = 1;
+       else
+               host->dma_done = 1;
+       spin_unlock_irqrestore(&host->dma_lock, flags);
+       if (done)
+               mmc_omap_xfer_done(host, data);
+}
+
+static void
+mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+       host->cmd = NULL;
+
+       switch (cmd->flags & MMC_RSP_MASK) {
+       case MMC_RSP_NONE:
+               /* resp 0 */
+               break;
+       case MMC_RSP_SHORT:
+               /* response types 1, 1b, 3, 4, 5, 6 */
+               cmd->resp[0] =
+                       OMAP_MMC_READ(host->base, RSP6) |
+                       (OMAP_MMC_READ(host->base, RSP7) << 16);
+               DBG("MMC%d: Response %08x\n", host->id, cmd->resp[0]);
+               break;
+       case MMC_RSP_LONG:
+               /* response type 2 */
+               cmd->resp[3] =
+                       OMAP_MMC_READ(host->base, RSP0) |
+                       (OMAP_MMC_READ(host->base, RSP1) << 16);
+               cmd->resp[2] =
+                       OMAP_MMC_READ(host->base, RSP2) |
+                       (OMAP_MMC_READ(host->base, RSP3) << 16);
+               cmd->resp[1] =
+                       OMAP_MMC_READ(host->base, RSP4) |
+                       (OMAP_MMC_READ(host->base, RSP5) << 16);
+               cmd->resp[0] =
+                       OMAP_MMC_READ(host->base, RSP6) |
+                       (OMAP_MMC_READ(host->base, RSP7) << 16);
+               DBG("MMC%d: Response %08x %08x %08x %08x\n", host->id,
+                   cmd->resp[0], cmd->resp[1],
+                   cmd->resp[2], cmd->resp[3]);
+               break;
+       }
+
+       if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
+               DBG("MMC%d: End request, err %x\n", host->id, cmd->error);
+               host->mrq = NULL;
+               clk_unuse(host->fclk);
+               mmc_request_done(host->mmc, cmd->mrq);
+       }
+}
+
+/* PIO only */
+static void
+mmc_omap_sg_to_buf(struct mmc_omap_host *host)
+{
+       struct scatterlist *sg;
+
+       sg = host->data->sg + host->sg_idx;
+       host->buffer_bytes_left = sg->length;
+       host->buffer = page_address(sg->page) + sg->offset;
+       if (host->buffer_bytes_left > host->total_bytes_left)
+               host->buffer_bytes_left = host->total_bytes_left;
+}
+
+/* PIO only */
+static void
+mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
+{
+       int n;
+       void __iomem *reg;
+       u16 *p;
+
+       if (host->buffer_bytes_left == 0) {
+               host->sg_idx++;
+               BUG_ON(host->sg_idx == host->sg_len);
+               mmc_omap_sg_to_buf(host);
+       }
+       n = 64;
+       if (n > host->buffer_bytes_left)
+               n = host->buffer_bytes_left;
+       host->buffer_bytes_left -= n;
+       host->total_bytes_left -= n;
+       host->data->bytes_xfered += n;
+
+       /* Optimize the loop a bit by calculating the register only
+        * once */
+       reg = host->base + OMAP_MMC_REG_DATA;
+       p = host->buffer;
+       n /= 2;
+       if (write) {
+               while (n--)
+                       __raw_writew(*p++, reg);
+       } else {
+               while (n-- > 0)
+                       *p++ = __raw_readw(reg);
+       }
+       host->buffer = p;
+}
+
+static inline void mmc_omap_report_irq(u16 status)
+{
+       static const char *mmc_omap_status_bits[] = {
+               "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO",
+               "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR"
+       };
+       int i, c = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
+               if (status & (1 << i)) {
+                       if (c)
+                               printk(" ");
+                       printk("%s", mmc_omap_status_bits[i]);
+                       c++;
+               }
+}
+
+static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id;
+       u16 status;
+       int end_command;
+       int end_transfer;
+       int transfer_error;
+
+       if (host->cmd == NULL && host->data == NULL) {
+               status = OMAP_MMC_READ(host->base, STAT);
+               printk(KERN_INFO "MMC%d: Spurious interrupt 0x%04x\n", host->id, status);
+               if (status != 0) {
+                       OMAP_MMC_WRITE(host->base, STAT, status);
+                       OMAP_MMC_WRITE(host->base, IE, 0);
+               }
+               return IRQ_HANDLED;
+       }
+
+       end_command = 0;
+       end_transfer = 0;
+       transfer_error = 0;
+
+       while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) {
+               OMAP_MMC_WRITE(host->base, STAT, status); // Reset status bits
+#ifdef CONFIG_MMC_DEBUG
+               printk(KERN_DEBUG "\tMMC IRQ %04x (CMD %d): ", status,
+                      host->cmd != NULL ? host->cmd->opcode : -1);
+               mmc_omap_report_irq(status);
+               printk("\n");
+#endif
+               if (host->total_bytes_left) {
+                       if ((status & OMAP_MMC_STAT_A_FULL) ||
+                           (status & OMAP_MMC_STAT_END_OF_DATA))
+                               mmc_omap_xfer_data(host, 0);
+                       if (status & OMAP_MMC_STAT_A_EMPTY)
+                               mmc_omap_xfer_data(host, 1);
+               }
+
+               if (status & OMAP_MMC_STAT_END_OF_DATA) {
+                       // Block sent/received
+                       end_transfer = 1;
+               }
+
+               if (status & OMAP_MMC_STAT_DATA_TOUT) {
+                       // Data timeout
+                       printk(KERN_DEBUG "MMC%d: Data timeout\n", host->id);
+                       if (host->data) {
+                               host->data->error |= MMC_ERR_TIMEOUT;
+                               transfer_error = 1;
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_DATA_CRC) {
+                       // Data CRC error
+                       if (host->data) {
+                               host->data->error |= MMC_ERR_BADCRC;
+                               printk(KERN_DEBUG "MMC%d: Data CRC error, bytes left %d\n",
+                                      host->id, host->total_bytes_left);
+                               transfer_error = 1;
+                       } else {
+                               printk(KERN_DEBUG "MMC%d: Data CRC error\n",
+                                      host->id);
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_CMD_TOUT) {
+                       /* Timeouts are routine with some commands */
+                       if (host->cmd) {
+                               if (host->cmd->opcode != MMC_ALL_SEND_CID &&
+                                   host->cmd->opcode != MMC_SEND_OP_COND &&
+                                   host->cmd->opcode != MMC_APP_CMD &&
+                                   !mmc_omap_cover_is_open(host))
+                                       printk(KERN_ERR "MMC%d: Command timeout, CMD%d\n",
+                                              host->id, host->cmd->opcode);
+                               host->cmd->error |= MMC_ERR_TIMEOUT;
+                               end_command = 1;
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_CMD_CRC) {
+                       // Command CRC error
+                       if (host->cmd) {
+                               printk(KERN_ERR "MMC%d: Command CRC error (CMD%d, arg 0x%08x)\n",
+                                      host->id, host->cmd->opcode,
+                                      host->cmd->arg);
+                               host->cmd->error |= MMC_ERR_BADCRC;
+                               end_command = 1;
+                       } else
+                               printk(KERN_ERR "MMC%d: Command CRC error without cmd?\n", host->id);
+               }
+
+               if (status & OMAP_MMC_STAT_OCR_BUSY) {
+                       /* OCR Busy ... happens a lot */
+                       if (host->cmd && host->cmd->opcode != MMC_SEND_OP_COND
+                               && host->cmd->opcode != MMC_SET_RELATIVE_ADDR) {
+                               DBG("MMC%d: OCR busy error, CMD%d\n",
+                                      host->id, host->cmd->opcode);
+                       }
+               }
+
+               if (status & OMAP_MMC_STAT_CARD_ERR) {
+                       if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
+                               u32 response = OMAP_MMC_READ(host->base, RSP6)
+                                       | (OMAP_MMC_READ(host->base, RSP7) << 16);
+                               /* STOP sometimes sets must-ignore bits */
+                               if (!(response & (R1_CC_ERROR
+       | R1_ILLEGAL_COMMAND
+       | R1_COM_CRC_ERROR))) {
+                                       end_command = 1;
+                                       continue;
+                               }
+                       }
+
+                       // Card status error
+                       printk(KERN_DEBUG "MMC%d: Card status error (CMD%d)\n",
+                              host->id, host->cmd->opcode);
+                       if (host->cmd) {
+                               host->cmd->error |= MMC_ERR_FAILED;
+                               end_command = 1;
+                       }
+                       if (host->data) {
+                               host->data->error |= MMC_ERR_FAILED;
+                               transfer_error = 1;
+                       }
+               }
+
+               /*
+                * NOTE: On 1610 the END_OF_CMD may come too early when
+                *       starting a write 
+                */
+               if ((status & OMAP_MMC_STAT_END_OF_CMD) &&
+                   (!(status & OMAP_MMC_STAT_A_EMPTY))) {
+                       // End of command phase
+                       end_command = 1;
+               }
+       }
+
+       if (end_command) {
+               mmc_omap_cmd_done(host, host->cmd);
+       }
+       if (transfer_error)
+               mmc_omap_xfer_done(host, host->data);
+       else if (end_transfer)
+               mmc_omap_end_of_data(host, host->data);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
+
+       DBG("MMC%d cover is now %s\n", host->id,
+           omap_get_gpio_datain(host->switch_pin) ? "open" : "closed");
+       schedule_work(&host->switch_work);
+
+       return IRQ_HANDLED;
+}
+
+static void mmc_omap_switch_timer(unsigned long arg)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) arg;
+
+       schedule_work(&host->switch_work);
+}
+
+/* FIXME: Handle card insertion and removal properly. Maybe use a mask
+ * for MMC state? */
+static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask)
+{
+       if (machine_is_omap_h4()) {
+               if (mmc_mask & 0x1)
+                       printk("XXX card in slot 1\n");
+               if (mmc_mask & 0x2)
+                       printk("XXX card in slot 2\n");
+       } else {
+               /* Assume card detect connected to cover switch */
+               if (mmc_mask & 0x2)
+                       printk("XXX cover open\n");
+               else
+                       printk("XXX cover closed\n");
+       }
+}
+
+static void mmc_omap_switch_handler(void *data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+       struct mmc_card *card;
+       static int complained = 0;
+       int cards = 0, cover_open;
+
+       if (host->switch_pin == -1)
+               return;
+       cover_open = mmc_omap_cover_is_open(host);
+       if (cover_open != host->switch_last_state) {
+               kobject_uevent(&host->dev->kobj, KOBJ_CHANGE, &dev_attr_cover_switch.attr);
+               host->switch_last_state = cover_open;
+       }
+       DBG("MMC cover switch handler started\n");
+       mmc_detect_change(host->mmc, 0);
+       list_for_each_entry(card, &host->mmc->cards, node) {
+               if (mmc_card_present(card))
+                       cards++;
+       }
+       DBG("MMC%d: %d card(s) present\n", host->id, cards);
+       if (mmc_omap_cover_is_open(host)) {
+               if (!complained) {
+                       printk(KERN_INFO "MMC%d: cover is open\n", host->id);
+                       complained = 1;
+               }
+               if (mmc_omap_enable_poll)
+                       mod_timer(&host->switch_timer, jiffies +
+                               msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY));
+       } else {
+               complained = 0;
+       }
+}
+
+/* prepare to transfer the next segment of a scatterlist */
+static void
+mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       int dma_ch = host->dma_ch;
+       unsigned long data_addr;
+       u16 buf, frame;
+       u32 count;
+       struct scatterlist *sg = &data->sg[host->sg_idx];
+       int src_port = 0;
+       int dst_port = 0;
+       int sync_dev = 0;
+
+       data_addr = io_v2p((void __force *) host->base) + OMAP_MMC_REG_DATA;
+       frame = 1 << data->blksz_bits;
+       count = (u32)sg_dma_len(sg);
+
+       /* the MMC layer is confused about single block writes... */
+       if ((data->blocks == 1) && (count > (1 << data->blksz_bits))) {
+               pr_debug("patch bogus single block length! %d > %d\n",
+                               count, frame);
+               count = frame;
+       }
+       host->dma_len = count;
+
+       /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx.
+        * Use 16 or 32 word frames when the blocksize is at least that large.
+        * Blocksize is usually 512 bytes; but not for some SD reads.
+        */
+       if (cpu_is_omap15xx() && frame > 32)
+               frame = 32;
+       else if (frame > 64)
+               frame = 64;
+       count /= frame;
+       frame >>= 1;
+
+       if (!(data->flags & MMC_DATA_WRITE)) {
+               buf = 0x800f | ((frame - 1) << 8);
+
+               if (cpu_class_is_omap1()) {
+                       src_port = OMAP_DMA_PORT_TIPB;
+                       dst_port = OMAP_DMA_PORT_EMIFF;
+               }
+               if (cpu_is_omap24xx())
+                       sync_dev = OMAP24XX_DMA_MMC1_RX;
+
+               omap_set_dma_src_params(dma_ch, src_port,
+                                       OMAP_DMA_AMODE_CONSTANT,
+                                       data_addr, 0, 0);
+               omap_set_dma_dest_params(dma_ch, dst_port,
+                                        OMAP_DMA_AMODE_POST_INC,
+                                        sg_dma_address(sg), 0, 0);
+               omap_set_dma_dest_data_pack(dma_ch, 1);
+               omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+       } else {
+               buf = 0x0f80 | ((frame - 1) << 0);
+
+               if (cpu_class_is_omap1()) {
+                       src_port = OMAP_DMA_PORT_EMIFF;
+                       dst_port = OMAP_DMA_PORT_TIPB;
+               }
+               if (cpu_is_omap24xx())
+                       sync_dev = OMAP24XX_DMA_MMC1_TX;
+
+               omap_set_dma_dest_params(dma_ch, dst_port,
+                                        OMAP_DMA_AMODE_CONSTANT,
+                                        data_addr, 0, 0);
+               omap_set_dma_src_params(dma_ch, src_port,
+                                       OMAP_DMA_AMODE_POST_INC,
+                                       sg_dma_address(sg), 0, 0);
+               omap_set_dma_src_data_pack(dma_ch, 1);
+               omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+       }
+
+       /* Max limit for DMA frame count is 0xffff */
+       if (unlikely(count > 0xffff))
+               BUG();
+
+       OMAP_MMC_WRITE(host->base, BUF, buf);
+       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
+                                    frame, count, OMAP_DMA_SYNC_FRAME,
+                                    sync_dev, 0);
+}
+
+/* a scatterlist segment completed */
+static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
+{
+       struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+       struct mmc_data *mmcdat = host->data;
+
+       if (unlikely(host->dma_ch < 0)) {
+               printk(KERN_ERR "MMC%d: DMA callback while DMA not enabled\n",
+                      host->id);
+               return;
+       }
+       /* FIXME: We really should do something to _handle_ the errors */
+       if (ch_status & OMAP_DMA_TOUT_IRQ) {
+               printk(KERN_ERR "MMC%d: DMA timeout\n", host->id);
+               return;
+       }
+       if (ch_status & OMAP_DMA_DROP_IRQ) {
+               printk(KERN_ERR "MMC%d: DMA sync error\n", host->id);
+               return;
+       }
+       if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
+               /* REVISIT we should be able to avoid getting IRQs with
+                * just SYNC status ...
+                */
+               if ((ch_status & ~OMAP1_DMA_SYNC_IRQ))
+                       pr_debug("MMC%d: DMA channel status: %04x\n",
+                              host->id, ch_status);
+               return;
+       }
+       mmcdat->bytes_xfered += host->dma_len;
+
+       pr_debug("\tMMC DMA %d bytes CB %04x (%d segments to go), %p\n",
+               host->dma_len, ch_status,
+               host->sg_len - host->sg_idx - 1, host->data);
+
+       host->sg_idx++;
+       if (host->sg_idx < host->sg_len) {
+               mmc_omap_prepare_dma(host, host->data);
+               omap_start_dma(host->dma_ch);
+       } else
+               mmc_omap_dma_done(host, host->data);
+}
+
+static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data)
+{
+       const char *dev_name;
+       int sync_dev, dma_ch, is_read, r;
+
+       is_read = !(data->flags & MMC_DATA_WRITE);
+       del_timer_sync(&host->dma_timer);
+       if (host->dma_ch >= 0) {
+               if (is_read == host->dma_is_read)
+                       return 0;
+               omap_free_dma(host->dma_ch);
+               host->dma_ch = -1;
+       }
+
+       if (is_read) {
+               if (host->id == 1) {
+                       sync_dev = OMAP_DMA_MMC_RX;
+                       dev_name = "MMC1 read";
+               } else {
+                       sync_dev = OMAP_DMA_MMC2_RX;
+                       dev_name = "MMC2 read";
+               }
+       } else {
+               if (host->id == 1) {
+                       sync_dev = OMAP_DMA_MMC_TX;
+                       dev_name = "MMC1 write";
+               } else {
+                       sync_dev = OMAP_DMA_MMC2_TX;
+                       dev_name = "MMC2 write";
+               }
+       }
+       r = omap_request_dma(sync_dev, dev_name, mmc_omap_dma_cb,
+                            host, &dma_ch);
+       if (r != 0) {
+               printk("MMC%d: omap_request_dma() failed with %d\n",
+                      host->id, r);
+               return r;
+       }
+       host->dma_ch = dma_ch;
+       host->dma_is_read = is_read;
+
+       return 0;
+}
+
+static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       u16 reg;
+
+       reg = OMAP_MMC_READ(host->base, SDIO);
+       reg &= ~(1 << 5);
+       OMAP_MMC_WRITE(host->base, SDIO, reg);
+       /* Set maximum timeout */
+       OMAP_MMC_WRITE(host->base, CTO, 0xff);
+}
+
+static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       int timeout;
+       u16 reg;
+
+       /* Convert ns to clock cycles by assuming 20MHz frequency
+        * 1 cycle at 20MHz = 500 ns
+        */
+       timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
+
+       /* Some cards require more time to do at least the first read operation */
+       timeout = timeout << 4;
+
+       /* Check if we need to use timeout multiplier register */
+       reg = OMAP_MMC_READ(host->base, SDIO);
+       if (timeout > 0xffff) {
+               reg |= (1 << 5);
+               timeout /= 1024;
+       } else
+               reg &= ~(1 << 5);
+       OMAP_MMC_WRITE(host->base, SDIO, reg);
+       OMAP_MMC_WRITE(host->base, DTO, timeout);
+}
+
+static void
+mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+{
+       struct mmc_data *data = req->data;
+       int i, use_dma, block_size;
+       unsigned sg_len;
+
+       host->data = data;
+       if (data == NULL) {
+               OMAP_MMC_WRITE(host->base, BLEN, 0);
+               OMAP_MMC_WRITE(host->base, NBLK, 0);
+               OMAP_MMC_WRITE(host->base, BUF, 0);
+               host->dma_in_use = 0;
+               set_cmd_timeout(host, req);
+               return;
+       }
+
+
+       block_size = 1 << data->blksz_bits;
+
+       OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
+       OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);
+       set_data_timeout(host, req);
+
+       /* cope with calling layer confusion; it issues "single
+        * block" writes using multi-block scatterlists.
+        */
+       sg_len = (data->blocks == 1) ? 1 : data->sg_len;
+
+       /* Only do DMA for entire blocks */
+       use_dma = host->use_dma;
+       if (use_dma) {
+               for (i = 0; i < sg_len; i++) {
+                       if ((data->sg[i].length % block_size) != 0) {
+                               use_dma = 0;
+                               break;
+                       }
+               }
+       }
+
+       host->sg_idx = 0;
+       if (use_dma) {
+               if (mmc_omap_get_dma_channel(host, data) == 0) {
+                       enum dma_data_direction dma_data_dir;
+
+                       if (data->flags & MMC_DATA_WRITE)
+                               dma_data_dir = DMA_TO_DEVICE;
+                       else
+                               dma_data_dir = DMA_FROM_DEVICE;
+
+                       host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+                                               sg_len, dma_data_dir);
+                       host->total_bytes_left = 0;
+                       mmc_omap_prepare_dma(host, req->data);
+                       host->brs_received = 0;
+                       host->dma_done = 0;
+                       host->dma_in_use = 1;
+               } else
+                       use_dma = 0;
+       }
+
+       /* Revert to PIO? */
+       if (!use_dma) {
+               OMAP_MMC_WRITE(host->base, BUF, 0x1f1f);
+               host->total_bytes_left = data->blocks * block_size;
+               host->sg_len = sg_len;
+               mmc_omap_sg_to_buf(host);
+               host->dma_in_use = 0;
+       }
+
+       pr_debug("MMC%d: %s %s %s, DTO %d cycles + %d ns, "
+                       "%d blocks of %d bytes, %d segments\n",
+               host->id, use_dma ? "DMA" : "PIO",
+               (data->flags & MMC_DATA_STREAM) ? "stream" : "block",
+               (data->flags & MMC_DATA_WRITE) ? "write" : "read",
+               data->timeout_clks, data->timeout_ns, data->blocks,
+               block_size, host->sg_len);
+}
+
+static inline int is_broken_card(struct mmc_card *card)
+{
+       int i;
+       struct mmc_cid *c = &card->cid;
+       static const struct broken_card_cid {
+               unsigned int manfid;
+               char prod_name[8];
+               unsigned char hwrev;
+               unsigned char fwrev;
+       } broken_cards[] = {
+               { 0x00150000, "\x30\x30\x30\x30\x30\x30\x15\x00", 0x06, 0x03 },
+       };
+
+       for (i = 0; i < sizeof(broken_cards)/sizeof(broken_cards[0]); i++) {
+               const struct broken_card_cid *b = broken_cards + i;
+
+               if (b->manfid != c->manfid)
+                       continue;
+               if (memcmp(b->prod_name, c->prod_name, sizeof(b->prod_name)) != 0)
+                       continue;
+               if (b->hwrev != c->hwrev || b->fwrev != c->fwrev)
+                       continue;
+               return 1;
+       }
+       return 0;
+}
+
+static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+
+       WARN_ON(host->mrq != NULL);
+
+       host->mrq = req;
+
+       /* Some cards (vendor left unnamed to protect the guilty) seem to
+        * require this delay after power-up. Otherwise we'll get mysterious
+        * data timeouts. */
+       if (req->cmd->opcode == MMC_SEND_CSD) {
+               struct mmc_card *card;
+               int broken_present = 0;
+
+               list_for_each_entry(card, &mmc->cards, node) {
+                       if (is_broken_card(card)) {
+                               broken_present = 1;
+                               break;
+                       }
+               }
+               if (broken_present) {
+                       static int complained = 0;
+
+                       if (!complained) {
+                               printk(KERN_WARNING "MMC%d: Broken card workaround enabled\n",
+                                      host->id);
+                               complained = 1;
+                       }
+                       if (in_interrupt()) {
+                               /* This is nasty */
+                                printk(KERN_ERR "Sleeping in IRQ handler, FIXME please!\n");
+                                dump_stack();
+                                mdelay(100);
+                       } else {
+                               set_current_state(TASK_UNINTERRUPTIBLE);
+                               schedule_timeout(100 * HZ / 1000);
+                       }
+               }
+       }
+
+       /* only touch fifo AFTER the controller readies it */
+       mmc_omap_prepare_data(host, req);
+       mmc_omap_start_command(host, req->cmd);
+       if (host->dma_in_use)
+               omap_start_dma(host->dma_ch);
+}
+
+static void innovator_fpga_socket_power(int on)
+{
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
+
+       if (on) {
+               fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+                    OMAP1510_FPGA_POWER);
+       } else {
+               fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+                    OMAP1510_FPGA_POWER);
+       }
+#endif
+}
+
+/*
+ * Turn the socket power on/off. Innovator uses FPGA, most boards
+ * probably use GPIO.
+ */
+static void mmc_omap_power(struct mmc_omap_host *host, int on)
+{
+       if (on) {
+               if (machine_is_omap_innovator())
+                       innovator_fpga_socket_power(1);
+               else if (machine_is_omap_h2())
+                       tps65010_set_gpio_out_value(GPIO3, HIGH);
+               else if (machine_is_omap_h3())
+                       /* GPIO 4 of TPS65010 sends SD_EN signal */
+                       tps65010_set_gpio_out_value(GPIO4, HIGH);
+               else if (cpu_is_omap24xx()) {
+                       u16 reg = OMAP_MMC_READ(host->base, CON);
+                       OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11));
+               } else
+                       if (host->power_pin >= 0)
+                               omap_set_gpio_dataout(host->power_pin, 1);
+       } else {
+               if (machine_is_omap_innovator())
+                       innovator_fpga_socket_power(0);
+               else if (machine_is_omap_h2())
+                       tps65010_set_gpio_out_value(GPIO3, LOW);
+               else if (machine_is_omap_h3())
+                       tps65010_set_gpio_out_value(GPIO4, LOW);
+               else if (cpu_is_omap24xx()) {
+                       u16 reg = OMAP_MMC_READ(host->base, CON);
+                       OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11));
+               } else
+                       if (host->power_pin >= 0)
+                               omap_set_gpio_dataout(host->power_pin, 0);
+       }
+}
+
+static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+       int dsor;
+       int realclock, i;
+
+       DBG("MMC%d: set_ios: clock %dHz busmode %d powermode %d Vdd %d.%02d\n",
+           host->id, ios->clock, ios->bus_mode, ios->power_mode,
+           ios->vdd / 100, ios->vdd % 100);
+
+       if (ios->power_mode == MMC_POWER_UP && ios->clock < 400000)
+               realclock = 400000;             /* Fix for broken stack */
+       else
+               realclock = ios->clock;
+
+       if (ios->clock == 0)
+               dsor = 0;
+       else {
+               int func_clk_rate = clk_get_rate(host->fclk);
+
+               dsor = func_clk_rate / realclock;
+               if (dsor < 1)
+                       dsor = 1;
+
+               if (func_clk_rate / dsor > realclock)
+                       dsor++;
+
+               if (dsor > 250)
+                       dsor = 250;
+               dsor++;
+
+               if (ios->bus_width == MMC_BUS_WIDTH_4)
+                       dsor |= 1 << 15;
+       }
+
+       switch (ios->power_mode) {
+       case MMC_POWER_OFF:
+               mmc_omap_power(host, 0);
+               break;
+       case MMC_POWER_UP:
+       case MMC_POWER_ON:
+               mmc_omap_power(host, 1);
+               dsor |= 1<<11;
+               break;
+       }
+
+       host->bus_mode = ios->bus_mode;
+       if (omap_has_menelaus()) {
+               if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+                       menelaus_mmc_opendrain(1);
+               else
+                       menelaus_mmc_opendrain(0);
+       }
+       host->hw_bus_mode = host->bus_mode;
+
+       clk_use(host->fclk);
+
+       /* On insanely high arm_per frequencies something sometimes
+        * goes somehow out of sync, and the POW bit is not being set,
+        * which results in the while loop below getting stuck.
+        * Writing to the CON register twice seems to do the trick. */
+       for (i = 0; i < 2; i++)
+               OMAP_MMC_WRITE(host->base, CON, dsor);
+       if (ios->power_mode == MMC_POWER_UP) {
+               /* Send clock cycles, poll completion */
+               OMAP_MMC_WRITE(host->base, IE, 0);
+               OMAP_MMC_WRITE(host->base, STAT, 0xffff);
+               OMAP_MMC_WRITE(host->base, CMD, 1<<7);
+               while (0 == (OMAP_MMC_READ(host->base, STAT) & 1));
+               OMAP_MMC_WRITE(host->base, STAT, 1);
+       }
+       clk_unuse(host->fclk);
+}
+
+static int mmc_omap_get_ro(struct mmc_host *mmc)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+
+       return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
+}
+
+static struct mmc_host_ops mmc_omap_ops = {
+       .request        = mmc_omap_request,
+       .set_ios        = mmc_omap_set_ios,
+       .get_ro         = mmc_omap_get_ro,
+};
+
+static int __init mmc_omap_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_mmc_conf *minfo = dev->platform_data;
+       struct mmc_host *mmc;
+       struct mmc_omap_host *host = NULL;
+       int ret = 0;
+
+       if (pdev->resource[0].flags != IORESOURCE_MEM
+           || pdev->resource[1].flags != IORESOURCE_IRQ) {
+               printk(KERN_ERR "mmc_omap_probe: invalid resource type\n");
+               return -ENODEV;
+       }
+
+       if (!request_mem_region(pdev->resource[0].start,
+                               pdev->resource[0].end - pdev->resource[0].start + 1, 
+                               pdev->name)) {
+               dev_dbg(&pdev->dev, "request_mem_region failed\n");
+               return -EBUSY;
+       }
+
+       mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+
+       spin_lock_init(&host->dma_lock);
+       init_timer(&host->dma_timer);
+       host->dma_timer.function = mmc_omap_dma_timer;
+       host->dma_timer.data = (unsigned long) host;
+
+       host->id = pdev->id;
+
+       if (cpu_is_omap24xx()) {
+               host->iclk = clk_get(dev, "mmc_ick");
+               if (IS_ERR(host->iclk))
+                       goto out;
+               clk_use(host->iclk);
+       }
+
+       if (!cpu_is_omap24xx())
+               host->fclk = clk_get(dev,
+                                   (host->id == 1) ? "mmc1_ck" : "mmc2_ck");
+       else
+               host->fclk = clk_get(dev, "mmc_fck");
+
+       if (IS_ERR(host->fclk)) {
+               ret = PTR_ERR(host->fclk);
+               goto out;
+       }
+
+       /* REVISIT:
+        * Also, use minfo->cover to decide how to manage
+        * the card detect sensing.
+        */
+       host->power_pin = minfo->power_pin;
+       host->switch_pin = minfo->switch_pin;
+       host->wp_pin = minfo->wp_pin;
+       host->use_dma = 1;
+       host->dma_ch = -1;
+
+       host->irq = pdev->resource[1].start;
+       host->base = (void __iomem *)pdev->resource[0].start;
+
+        if (minfo->wire4)
+                mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+       mmc->ops = &mmc_omap_ops;
+       mmc->f_min = 400000;
+       mmc->f_max = 24000000;
+       mmc->ocr_avail = MMC_VDD_33_34;
+
+       /* Use scatterlist DMA to reduce per-transfer costs.
+        * NOTE max_seg_size assumption that small blocks aren't
+        * normally used (except e.g. for reading SD registers).
+        */
+       mmc->max_phys_segs = 32;
+       mmc->max_hw_segs = 32;
+       mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */
+       mmc->max_seg_size = mmc->max_sectors * 512;
+
+       if (host->power_pin >= 0) {
+               if ((ret = omap_request_gpio(host->power_pin)) != 0) {
+                       printk(KERN_ERR "MMC%d: Unable to get GPIO pin for MMC power\n",
+                              host->id);
+                       goto out;
+               }
+               omap_set_gpio_direction(host->power_pin, 0);
+       }
+
+       ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
+       if (ret)
+               goto out;
+
+       host->dev = dev;
+       dev_set_drvdata(dev, host);
+
+       mmc_add_host(mmc);
+
+       if (host->switch_pin >= 0) {
+               INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
+               init_timer(&host->switch_timer);
+               host->switch_timer.function = mmc_omap_switch_timer;
+               host->switch_timer.data = (unsigned long) host;
+               if (omap_request_gpio(host->switch_pin) != 0) {
+                       printk(KERN_WARNING "MMC%d: Unable to get GPIO pin for MMC cover switch\n",
+                              host->id);
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+
+               omap_set_gpio_direction(host->switch_pin, 1);
+               set_irq_type(OMAP_GPIO_IRQ(host->switch_pin), IRQT_RISING);
+               ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin),
+                                 mmc_omap_switch_irq, 0, DRIVER_NAME, host);
+               if (ret) {
+                       printk(KERN_WARNING "MMC%d: Unable to get IRQ for MMC cover switch\n",
+                              host->id);
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+               ret = device_create_file(dev, &dev_attr_cover_switch);
+               if (ret == 0) {
+                       ret = device_create_file(dev, &dev_attr_enable_poll);
+                       if (ret != 0)
+                               device_remove_file(dev, &dev_attr_cover_switch);
+               }
+               if (ret) {
+                       printk(KERN_WARNING "MMC%d: Unable to create sysfs attributes\n", 
+                              host->id);
+                       free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       goto no_switch;
+               }
+               if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host))
+                       schedule_work(&host->switch_work);
+       }
+
+       if (omap_has_menelaus())
+               menelaus_mmc_register(mmc_omap_switch_callback, &host);
+
+no_switch:
+       return 0;
+
+out:
+       /* FIXME: Free other resources too. */
+       if (host) {
+               if (host->iclk && !IS_ERR(host->iclk))
+                       clk_put(host->iclk);
+               if (host->fclk && !IS_ERR(host->fclk))
+                       clk_put(host->fclk);
+               mmc_free_host(host->mmc);
+       }
+       return ret;
+}
+
+static int __exit mmc_omap_remove(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+       dev_set_drvdata(dev, NULL);
+
+       if (host) {
+               mmc_remove_host(host->mmc);
+               free_irq(host->irq, host);
+               mmc_omap_power(host, 0);
+
+               if (host->power_pin >= 0)
+                       omap_free_gpio(host->power_pin);
+               if (host->switch_pin >= 0) {
+                       device_remove_file(dev, &dev_attr_enable_poll);
+                       device_remove_file(dev, &dev_attr_cover_switch);
+                       free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+                       omap_free_gpio(host->switch_pin);
+                       host->switch_pin = -1;
+                       del_timer_sync(&host->switch_timer);
+                       flush_scheduled_work();
+               }
+               if (host->iclk && !IS_ERR(host->iclk))
+                       clk_put(host->iclk);
+               if (host->fclk && !IS_ERR(host->fclk))
+                       clk_put(host->fclk);
+               mmc_free_host(host->mmc);
+       }
+
+       if (omap_has_menelaus())
+               menelaus_mmc_remove();
+
+       release_mem_region(pdev->resource[0].start, 
+                          pdev->resource[0].end - pdev->resource[0].start + 1);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int mmc_omap_suspend(struct device *dev, pm_message_t mesg)
+{
+       int ret = 0;
+       struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+       if (host && host->suspended)
+               return 0;
+
+       if (!irqs_disabled())
+               return -EAGAIN;
+
+       if (host) {
+               ret = mmc_suspend_host(host->mmc, mesg);
+               if (ret == 0)
+                       host->suspended = 1;
+       }
+       return ret;
+}
+
+static int mmc_omap_resume(struct device *dev)
+{
+       int ret = 0;
+       struct mmc_omap_host *host = dev_get_drvdata(dev);
+
+       if (host && !host->suspended)
+               return 0;
+
+       if (host) {
+               ret = mmc_resume_host(host->mmc);
+               if (ret == 0)
+                       host->suspended = 0;
+       }
+
+       return ret;
+}
+#else
+#define mmc_omap_suspend       NULL
+#define mmc_omap_resume                NULL
+#endif
+
+static struct device_driver mmc_omap_driver = {
+       .name           = DRIVER_NAME,
+       .bus            = &platform_bus_type,
+       .probe          = mmc_omap_probe,
+       .remove         = __exit_p(mmc_omap_remove),
+       .suspend        = mmc_omap_suspend,
+       .resume         = mmc_omap_resume,
+};
+
+static int __init mmc_omap_init(void)
+{
+       return driver_register(&mmc_omap_driver);
+}
+
+static void __exit mmc_omap_exit(void)
+{
+       driver_unregister(&mmc_omap_driver);
+}
+
+module_init(mmc_omap_init);
+module_exit(mmc_omap_exit);
+
+MODULE_DESCRIPTION("OMAP Multimedia Card driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(DRIVER_NAME);
+MODULE_AUTHOR("Juha Yrjölä");
diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h
new file mode 100644 (file)
index 0000000..c954d35
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef        DRIVERS_MEDIA_MMC_OMAP_H
+#define        DRIVERS_MEDIA_MMC_OMAP_H
+
+#define        OMAP_MMC_REG_CMD        0x00
+#define        OMAP_MMC_REG_ARGL       0x04
+#define        OMAP_MMC_REG_ARGH       0x08
+#define        OMAP_MMC_REG_CON        0x0c
+#define        OMAP_MMC_REG_STAT       0x10
+#define        OMAP_MMC_REG_IE         0x14
+#define        OMAP_MMC_REG_CTO        0x18
+#define        OMAP_MMC_REG_DTO        0x1c
+#define        OMAP_MMC_REG_DATA       0x20
+#define        OMAP_MMC_REG_BLEN       0x24
+#define        OMAP_MMC_REG_NBLK       0x28
+#define        OMAP_MMC_REG_BUF        0x2c
+#define OMAP_MMC_REG_SDIO      0x34
+#define        OMAP_MMC_REG_REV        0x3c
+#define        OMAP_MMC_REG_RSP0       0x40
+#define        OMAP_MMC_REG_RSP1       0x44
+#define        OMAP_MMC_REG_RSP2       0x48
+#define        OMAP_MMC_REG_RSP3       0x4c
+#define        OMAP_MMC_REG_RSP4       0x50
+#define        OMAP_MMC_REG_RSP5       0x54
+#define        OMAP_MMC_REG_RSP6       0x58
+#define        OMAP_MMC_REG_RSP7       0x5c
+#define        OMAP_MMC_REG_IOSR       0x60
+#define        OMAP_MMC_REG_SYSC       0x64
+#define        OMAP_MMC_REG_SYSS       0x68
+
+#define        OMAP_MMC_STAT_CARD_ERR          (1 << 14)
+#define        OMAP_MMC_STAT_CARD_IRQ          (1 << 13)
+#define        OMAP_MMC_STAT_OCR_BUSY          (1 << 12)
+#define        OMAP_MMC_STAT_A_EMPTY           (1 << 11)
+#define        OMAP_MMC_STAT_A_FULL            (1 << 10)
+#define        OMAP_MMC_STAT_CMD_CRC           (1 <<  8)
+#define        OMAP_MMC_STAT_CMD_TOUT          (1 <<  7)
+#define        OMAP_MMC_STAT_DATA_CRC          (1 <<  6)
+#define        OMAP_MMC_STAT_DATA_TOUT         (1 <<  5)
+#define        OMAP_MMC_STAT_END_BUSY          (1 <<  4)
+#define        OMAP_MMC_STAT_END_OF_DATA       (1 <<  3)
+#define        OMAP_MMC_STAT_CARD_BUSY         (1 <<  2)
+#define        OMAP_MMC_STAT_END_OF_CMD        (1 <<  0)
+
+#define OMAP_MMC_READ(base, reg)       __raw_readw((base) + OMAP_MMC_REG_##reg)
+#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg)
+
+/*
+ * Command types
+ */
+#define OMAP_MMC_CMDTYPE_BC    0
+#define OMAP_MMC_CMDTYPE_BCR   1
+#define OMAP_MMC_CMDTYPE_AC    2
+#define OMAP_MMC_CMDTYPE_ADTC  3
+
+#endif
index fd3b4a5fc2072653a6f2c919d5c9984004a87a04..120ef13fbf316844812c0f9d5c3a83ef4483fd05 100644 (file)
@@ -61,12 +61,14 @@ static void omap_set_vpp(struct map_info *map, int enable)
 {
        static int      count;
 
-       if (enable) {
-               if (count++ == 0)
-                       OMAP_EMIFS_CONFIG_REG |= OMAP_EMIFS_CONFIG_WP;
-       } else {
-               if (count && (--count == 0))
-                       OMAP_EMIFS_CONFIG_REG &= ~OMAP_EMIFS_CONFIG_WP;
+       if (!cpu_is_omap24xx()) {
+               if (enable) {
+                       if (count++ == 0)
+                               OMAP_EMIFS_CONFIG_REG |= OMAP_EMIFS_CONFIG_WP;
+               } else {
+                       if (count && (--count == 0))
+                               OMAP_EMIFS_CONFIG_REG &= ~OMAP_EMIFS_CONFIG_WP;
+               }
        }
 }
 
index 1fc4c134d9391f685eb1880ca90082d96cd30725..cc3111397f92b684b85a8b7f13ce3b28443619ff 100644 (file)
@@ -49,6 +49,12 @@ config MTD_NAND_SPIA
        help
          If you had to ask, you don't have one. Say 'N'.
 
+config MTD_NAND_OMAP
+        tristate "NAND Flash device on OMAP H3/H2/P2 or NETSTAR boards"
+       depends on ARM && ARCH_OMAP1 && MTD_NAND && (MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_NETSTAR || MACH_OMAP_PERSEUS2)
+        help
+          Support for NAND flash on Texas Instruments H3/H2/P2/NETSTAR platforms.
+
 config MTD_NAND_TOTO
        tristate "NAND Flash device on TOTO board"
        depends on ARCH_OMAP && MTD_NAND
@@ -190,5 +196,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
        help
          The simulator may simulate verious NAND flash chips for the
          MTD nand layer.
+
+config MTD_NAND_OMAP_HW
+       bool "OMAP HW NAND Flash controller support"
+        depends on ARM && ARCH_OMAP16XX && MTD_NAND
+
+       help
+         Driver for TI OMAP16xx hardware NAND flash controller.
+
 endmenu
index 41742026a52e7e45033f8a37ef57d7b0222c55df..dc2929f996bcea0d6b85a1bce666156ceef42e40 100644 (file)
@@ -18,5 +18,7 @@ obj-$(CONFIG_MTD_NAND_H1900)          += h1910.o
 obj-$(CONFIG_MTD_NAND_RTC_FROM4)       += rtc_from4.o
 obj-$(CONFIG_MTD_NAND_SHARPSL)         += sharpsl.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)         += nandsim.o
+obj-$(CONFIG_MTD_NAND_OMAP)            += omap-nand-flash.o
+obj-$(CONFIG_MTD_NAND_OMAP_HW)         += omap-hw.o
 
 nand-objs = nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/omap-hw.c b/drivers/mtd/nand/omap-hw.c
new file mode 100644 (file)
index 0000000..6afab16
--- /dev/null
@@ -0,0 +1,848 @@
+/*
+ *  drivers/mtd/nand/omap-hw.c
+ *
+ *  This is the MTD driver for OMAP 1710 internal HW nand controller.
+ *
+ *  Copyright (C) 2004 Nokia Corporation
+ * 
+ *  Author: Jarkko Lavinen <jarkko.lavinen@nokia.com>
+ *
+ *  Dma patches by Juha Yrjölä <juha.yrjola@nokia.com>
+ * 
+ *  $Id: omap-hw.c,v 1.1 2004/12/08 00:00:01 jlavi Exp $
+ *
+ * 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.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/dma.h>
+#include <asm/hardware/clock.h>
+
+#define NAND_BASE              0xfffbcc00
+#define NND_REVISION           0x00
+#define NND_ACCESS             0x04
+#define NND_ADDR_SRC           0x08
+#define NND_CTRL               0x10
+#define NND_MASK               0x14
+#define NND_STATUS             0x18
+#define NND_READY              0x1c
+#define NND_COMMAND            0x20
+#define NND_COMMAND_SEC                0x24
+#define NND_ECC_SELECT         0x28
+#define NND_ECC_START          0x2c
+#define NND_ECC_9              0x4c
+#define NND_RESET              0x50
+#define NND_FIFO               0x54
+#define NND_FIFOCTRL           0x58
+#define NND_PSC_CLK            0x5c
+#define NND_SYSTEST            0x60
+#define NND_SYSCFG             0x64
+#define NND_SYSSTATUS          0x68
+#define NND_FIFOTEST1          0x6c
+#define NND_FIFOTEST2          0x70
+#define NND_FIFOTEST3          0x74
+#define NND_FIFOTEST4          0x78
+#define NND_PSC1_CLK           0x8c
+#define NND_PSC2_CLK           0x90
+
+
+#define NND_CMD_READ1_LOWER    0x00
+#define NND_CMD_WRITE1_LOWER   0x00
+#define NND_CMD_READ1_UPPER    0x01
+#define NND_CMD_WRITE1_UPPER   0x01
+#define NND_CMD_PROGRAM_END    0x10
+#define NND_CMD_READ2_SPARE    0x50
+#define NND_CMD_WRITE2_SPARE   0x50
+#define NND_CMD_ERASE          0x60
+#define NND_CMD_STATUS         0x70
+#define NND_CMD_PROGRAM                0x80
+#define NND_CMD_READ_ID                0x90
+#define NND_CMD_ERASE_END      0xD0
+#define NND_CMD_RESET          0xFF
+
+
+#define NAND_Ecc_P1e           (1 << 0)
+#define NAND_Ecc_P2e           (1 << 1)
+#define NAND_Ecc_P4e           (1 << 2)
+#define NAND_Ecc_P8e           (1 << 3)
+#define NAND_Ecc_P16e          (1 << 4)
+#define NAND_Ecc_P32e          (1 << 5)
+#define NAND_Ecc_P64e          (1 << 6)
+#define NAND_Ecc_P128e         (1 << 7)
+#define NAND_Ecc_P256e         (1 << 8)
+#define NAND_Ecc_P512e         (1 << 9)
+#define NAND_Ecc_P1024e                (1 << 10)
+#define NAND_Ecc_P2048e                (1 << 11)
+
+#define NAND_Ecc_P1o           (1 << 16)
+#define NAND_Ecc_P2o           (1 << 17)
+#define NAND_Ecc_P4o           (1 << 18)
+#define NAND_Ecc_P8o           (1 << 19)
+#define NAND_Ecc_P16o          (1 << 20)
+#define NAND_Ecc_P32o          (1 << 21)
+#define NAND_Ecc_P64o          (1 << 22)
+#define NAND_Ecc_P128o         (1 << 23)
+#define NAND_Ecc_P256o         (1 << 24)
+#define NAND_Ecc_P512o         (1 << 25)
+#define NAND_Ecc_P1024o                (1 << 26)
+#define NAND_Ecc_P2048o                (1 << 27)
+
+#define TF(value)      (value ? 1 : 0)
+
+#define P2048e(a)      (TF(a & NAND_Ecc_P2048e)        << 0 )
+#define P2048o(a)      (TF(a & NAND_Ecc_P2048o)        << 1 )
+#define P1e(a)         (TF(a & NAND_Ecc_P1e)           << 2 )
+#define P1o(a)         (TF(a & NAND_Ecc_P1o)           << 3 )
+#define P2e(a)         (TF(a & NAND_Ecc_P2e)           << 4 )
+#define P2o(a)         (TF(a & NAND_Ecc_P2o)           << 5 )
+#define P4e(a)         (TF(a & NAND_Ecc_P4e)           << 6 )
+#define P4o(a)         (TF(a & NAND_Ecc_P4o)           << 7 )
+
+#define P8e(a)         (TF(a & NAND_Ecc_P8e)           << 0 )
+#define P8o(a)         (TF(a & NAND_Ecc_P8o)           << 1 )
+#define P16e(a)                (TF(a & NAND_Ecc_P16e)          << 2 )
+#define P16o(a)                (TF(a & NAND_Ecc_P16o)          << 3 )
+#define P32e(a)                (TF(a & NAND_Ecc_P32e)          << 4 )
+#define P32o(a)                (TF(a & NAND_Ecc_P32o)          << 5 )
+#define P64e(a)                (TF(a & NAND_Ecc_P64e)          << 6 )
+#define P64o(a)                (TF(a & NAND_Ecc_P64o)          << 7 )
+
+#define P128e(a)       (TF(a & NAND_Ecc_P128e)         << 0 )
+#define P128o(a)       (TF(a & NAND_Ecc_P128o)         << 1 )
+#define P256e(a)       (TF(a & NAND_Ecc_P256e)         << 2 )
+#define P256o(a)       (TF(a & NAND_Ecc_P256o)         << 3 )
+#define P512e(a)       (TF(a & NAND_Ecc_P512e)         << 4 )
+#define P512o(a)       (TF(a & NAND_Ecc_P512o)         << 5 )
+#define P1024e(a)      (TF(a & NAND_Ecc_P1024e)        << 6 )
+#define P1024o(a)      (TF(a & NAND_Ecc_P1024o)        << 7 )
+
+#define P8e_s(a)       (TF(a & NAND_Ecc_P8e)           << 0 )
+#define P8o_s(a)       (TF(a & NAND_Ecc_P8o)           << 1 )
+#define P16e_s(a)      (TF(a & NAND_Ecc_P16e)          << 2 )
+#define P16o_s(a)      (TF(a & NAND_Ecc_P16o)          << 3 )
+#define P1e_s(a)       (TF(a & NAND_Ecc_P1e)           << 4 )
+#define P1o_s(a)       (TF(a & NAND_Ecc_P1o)           << 5 )
+#define P2e_s(a)       (TF(a & NAND_Ecc_P2e)           << 6 )
+#define P2o_s(a)       (TF(a & NAND_Ecc_P2o)           << 7 )
+
+#define P4e_s(a)       (TF(a & NAND_Ecc_P4e)           << 0 )
+#define P4o_s(a)       (TF(a & NAND_Ecc_P4o)           << 1 )
+
+extern struct nand_oobinfo jffs2_oobinfo;
+
+/*
+ * MTD structure for OMAP board
+ */
+static struct mtd_info *omap_mtd;
+static struct clk *omap_nand_clk;
+static unsigned long omap_nand_base = io_p2v(NAND_BASE);
+
+
+static inline u32 nand_read_reg(int idx)
+{
+       return __raw_readl(omap_nand_base + idx);
+}
+
+static inline void nand_write_reg(int idx, u32 val)
+{
+       __raw_writel(val, omap_nand_base + idx);
+}
+
+static inline u8 nand_read_reg8(int idx)
+{
+       return __raw_readb(omap_nand_base + idx);
+}
+
+static inline void nand_write_reg8(int idx, u8 val)
+{
+       __raw_writeb(val, omap_nand_base + idx);
+}
+
+static void omap_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+       u32 l;
+
+       switch(chip) {
+       case -1:
+               l = nand_read_reg(NND_CTRL);
+               l |= (1 << 8) | (1 << 10) | (1 << 12) | (1 << 14);
+               nand_write_reg(NND_CTRL, l);
+               break;
+       case 0:
+               /* Also CS1, CS2, CS4 would be available */
+               l = nand_read_reg(NND_CTRL);
+               l &= ~(1 << 8);
+               nand_write_reg(NND_CTRL, l);
+               break;
+       default:
+               BUG();
+       }
+}
+
+static void nand_dma_cb(int lch, u16 ch_status, void *data)
+{
+       complete((struct completion *) data);
+}
+
+static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
+                                         unsigned int u32_count, int is_write)
+{
+       const int block_size = 16;
+       unsigned int block_count, len;
+       int r, dma_ch;
+       struct completion comp;
+       unsigned long fifo_reg;
+
+       r = omap_request_dma(OMAP_DMA_NAND, "NAND", nand_dma_cb, &comp, &dma_ch);
+       if (r < 0)
+               return r;
+       block_count = u32_count * 4 / block_size;
+       nand_write_reg(NND_FIFOCTRL, (block_size << 24) | block_count);
+       fifo_reg = NAND_BASE + NND_FIFO;
+       if (is_write) {
+               omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_TIPB,
+                                        OMAP_DMA_AMODE_CONSTANT, fifo_reg,
+                                        0, 0);
+               omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_EMIFF,
+                                       OMAP_DMA_AMODE_POST_INC,
+                                       virt_to_phys(addr),
+                                       0, 0);
+//             omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
+               /* Set POSTWRITE bit */
+               nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 16));
+       } else {
+               omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_TIPB,
+                                       OMAP_DMA_AMODE_CONSTANT, fifo_reg,
+                                       0, 0);
+               omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_EMIFF,
+                                        OMAP_DMA_AMODE_POST_INC,
+                                        virt_to_phys(addr),
+                                        0, 0);
+//             omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_8);
+               /* Set PREFETCH bit */
+               nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 17));
+       }
+       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, block_size / 4,
+                                    block_count, OMAP_DMA_SYNC_FRAME,
+                                    0, 0);
+       init_completion(&comp);
+
+       len = u32_count << 2;
+       consistent_sync(addr, len, DMA_TO_DEVICE);
+       omap_start_dma(dma_ch);
+       wait_for_completion(&comp);
+       omap_free_dma(dma_ch);
+       if (!is_write)
+               consistent_sync(addr, len, DMA_FROM_DEVICE);
+
+       nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) & ~((1 << 16) | (1 << 17)));
+       return 0;
+}
+
+static void fifo_read(u32 *out, unsigned int len)
+{
+       const int block_size = 16;
+       unsigned long status_reg, fifo_reg;
+       int c;
+
+       status_reg = omap_nand_base + NND_STATUS;
+       fifo_reg = omap_nand_base + NND_FIFO;
+       len = len * 4 / block_size;
+       nand_write_reg(NND_FIFOCTRL, (block_size << 24) | len);
+       nand_write_reg(NND_STATUS, 0x0f);
+       nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 17));
+       c = block_size / 4;
+       while (len--) {
+               int i;
+
+               while ((__raw_readl(status_reg) & (1 << 2)) == 0);
+               __raw_writel(0x0f, status_reg);
+               for (i = 0; i < c; i++) {
+                       u32 l = __raw_readl(fifo_reg);
+                       *out++ = l;
+               }
+       }
+       nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) & ~(1 << 17));
+       nand_write_reg(NND_STATUS, 0x0f);
+}
+
+static void omap_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       unsigned long access_reg;
+
+       if (likely(((unsigned long) buf & 3) == 0 && (len & 3) == 0)) {
+               int u32_count = len >> 2;
+               u32 *dest = (u32 *) buf;
+               /* If the transfer is big enough and the length divisible by
+                * 16, we try to use DMA transfer, or FIFO copy in case of
+                * DMA failure (e.g. all channels busy) */
+               if (u32_count > 64 && (u32_count & 3) == 0) {
+#if 1
+                       if (omap_nand_dma_transfer(mtd, buf, u32_count, 0) == 0)
+                               return;
+#endif
+                       /* In case of an error, fallback to FIFO copy */
+                       fifo_read((u32 *) buf, u32_count);
+                       return;
+               }
+               access_reg = omap_nand_base + NND_ACCESS;
+               /* Small buffers we just read directly */
+               while (u32_count--)
+                       *dest++ = __raw_readl(access_reg);
+       } else {
+               /* If we're not word-aligned, we use byte copy */
+               access_reg = omap_nand_base + NND_ACCESS;
+               while (len--)
+                       *buf++ = __raw_readb(access_reg);
+       }
+}
+
+static void omap_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       if (likely(((unsigned long) buf & 3) == 0 && (len & 3) == 0)) {
+               const u32 *src = (const u32 *) buf;
+
+               len >>= 2;
+#if 0
+               /* If the transfer is big enough and length divisible by 16,
+                * we try to use DMA transfer. */
+               if (len > 256 / 4 && (len & 3) == 0) {
+                       if (omap_nand_dma_transfer(mtd, (void *) buf, len, 1) == 0)
+                               return;
+                       /* In case of an error, fallback to CPU copy */
+               }
+#endif
+               while (len--)
+                       nand_write_reg(NND_ACCESS, *src++);
+       } else {
+               while (len--)
+                       nand_write_reg8(NND_ACCESS, *buf++);
+       }
+}
+
+static int omap_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       if (likely(((unsigned long) buf & 3) == 0 && (len & 3) == 0)) {
+               const u32 *dest = (const u32 *) buf;
+               len >>= 2;
+               while (len--)
+                       if (*dest++ != nand_read_reg(NND_ACCESS))
+                               return -EFAULT;
+       } else {
+               while (len--)
+                       if (*buf++ != nand_read_reg8(NND_ACCESS))
+                               return -EFAULT;
+       }
+       return 0;
+}
+
+static u_char omap_nand_read_byte(struct mtd_info *mtd)
+{
+       return nand_read_reg8(NND_ACCESS);
+}
+
+static void omap_nand_write_byte(struct mtd_info *mtd, u_char byte)
+{
+       nand_write_reg8(NND_ACCESS, byte);
+}
+
+static int omap_nand_dev_ready(struct mtd_info *mtd)
+{
+       u32 l;
+
+       l = nand_read_reg(NND_READY);
+       return l & 0x01;
+}
+
+static int nand_write_command(u8 cmd, u32 addr, int addr_valid)
+{
+       if (addr_valid) {
+               nand_write_reg(NND_ADDR_SRC, addr);
+               nand_write_reg8(NND_COMMAND, cmd);
+       } else {
+               nand_write_reg(NND_ADDR_SRC, 0);
+               nand_write_reg8(NND_COMMAND_SEC, cmd);
+       }
+       while (!omap_nand_dev_ready(NULL));
+       return 0;
+}
+
+/*
+ * Send command to NAND device
+ */
+static void omap_nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
+{
+       struct nand_chip *this = mtd->priv;
+
+       /*
+        * Write out the command to the device.
+        */
+       if (command == NAND_CMD_SEQIN) {
+               int readcmd;
+
+               if (column >= mtd->oobblock) {
+                       /* OOB area */
+                       column -= mtd->oobblock;
+                       readcmd = NAND_CMD_READOOB;
+               } else if (column < 256) {
+                       /* First 256 bytes --> READ0 */
+                       readcmd = NAND_CMD_READ0;
+               } else {
+                       column -= 256;
+                       readcmd = NAND_CMD_READ1;
+               }
+               nand_write_command(readcmd, 0, 0);
+       }
+
+       switch (command) {
+       case NAND_CMD_RESET:
+       case NAND_CMD_PAGEPROG:
+       case NAND_CMD_STATUS:
+       case NAND_CMD_ERASE2:
+               nand_write_command(command, 0, 0);
+               break;
+
+       case NAND_CMD_ERASE1:
+               nand_write_command(command, ((page_addr & 0xFFFFFF00) << 1) | (page_addr & 0XFF), 1);
+               break;
+
+       default:
+               nand_write_command(command, (page_addr << this->page_shift) | column, 1);
+       }
+}
+
+static void omap_nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr)
+{
+       struct nand_chip *this = mtd->priv;
+
+       if (command == NAND_CMD_READOOB) {
+               column += mtd->oobblock;
+               command = NAND_CMD_READ0;
+       }
+       switch (command) {
+       case NAND_CMD_RESET:
+       case NAND_CMD_PAGEPROG:
+       case NAND_CMD_STATUS:
+       case NAND_CMD_ERASE2:           
+               nand_write_command(command, 0, 0);
+               break;
+       case NAND_CMD_ERASE1:
+               nand_write_command(command, page_addr << this->page_shift >> 11, 1);
+               break;
+       default:
+               nand_write_command(command, (page_addr << 16) | column, 1);
+       }
+       if (command == NAND_CMD_READ0)
+               nand_write_command(NAND_CMD_READSTART, 0, 0);
+}
+
+/*
+ * Generate non-inverted ECC bytes.
+ *
+ * Using noninverted ECC can be considered ugly since writing a blank
+ * page ie. padding will clear the ECC bytes. This is no problem as long
+ * nobody is trying to write data on the seemingly unused page.
+ *
+ * Reading an erased page will produce an ECC mismatch between
+ * generated and read ECC bytes that has to be dealt with separately.
+ */
+static int omap_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+       u32 l;
+       int reg;
+       int n;
+       struct nand_chip *this = mtd->priv;
+
+       if (this->eccmode == NAND_ECC_HW12_2048)
+               n = 4;
+       else
+               n = 1;
+       reg = NND_ECC_START;
+       while (n--) {
+               l = nand_read_reg(reg);
+               *ecc_code++ = l;          // P128e, ..., P1e
+               *ecc_code++ = l >> 16;    // P128o, ..., P1o
+               // P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e
+               *ecc_code++ = ((l >> 8) & 0x0f) | ((l >> 20) & 0xf0);
+               reg += 4;
+       }
+       return 0;
+}
+
+/*
+ * This function will generate true ECC value, which can be used
+ * when correcting data read from NAND flash memory core
+ */
+static void gen_true_ecc(u8 *ecc_buf)
+{
+       u32 tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) | ((ecc_buf[2] & 0x0F) << 8);
+
+       ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp) );
+       ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
+       ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
+}
+
+/*
+ * This function compares two ECC's and indicates if there is an error.
+ * If the error can be corrected it will be corrected to the buffer
+ */
+static int omap_nand_compare_ecc(u8 *ecc_data1,   /* read from NAND memory */
+                                u8 *ecc_data2,   /* read from register */
+                                u8 *page_data)
+{
+       uint   i;
+       u8     tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
+       u8     comp0_bit[8], comp1_bit[8], comp2_bit[8];
+       u8     ecc_bit[24];
+       u8     ecc_sum = 0;
+       u8     find_bit = 0;
+       uint   find_byte = 0;
+       int    isEccFF;
+
+       isEccFF = ((*(u32 *)ecc_data1 & 0xFFFFFF) == 0xFFFFFF);
+
+       gen_true_ecc(ecc_data1);
+       gen_true_ecc(ecc_data2);
+
+       for (i = 0; i <= 2; i++) {
+               *(ecc_data1 + i) = ~(*(ecc_data1 + i));
+               *(ecc_data2 + i) = ~(*(ecc_data2 + i));
+       }
+
+       for (i = 0; i < 8; i++) {
+               tmp0_bit[i]      = *ecc_data1 % 2;
+               *ecc_data1       = *ecc_data1 / 2;
+       }
+
+       for (i = 0; i < 8; i++) {
+               tmp1_bit[i]      = *(ecc_data1 + 1) % 2;
+               *(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
+        }
+
+       for (i = 0; i < 8; i++) {
+               tmp2_bit[i]      = *(ecc_data1 + 2) % 2;
+               *(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
+       }
+
+       for (i = 0; i < 8; i++) {
+               comp0_bit[i]     = *ecc_data2 % 2;
+               *ecc_data2       = *ecc_data2 / 2;
+       }
+
+       for (i = 0; i < 8; i++) {
+               comp1_bit[i]     = *(ecc_data2 + 1) % 2;
+               *(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
+       }
+
+       for (i = 0; i < 8; i++) {
+               comp2_bit[i]     = *(ecc_data2 + 2) % 2;
+               *(ecc_data2 + 2) = *(ecc_data2 + 2) / 2;
+       }
+
+       for (i = 0; i< 6; i++ )
+               ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
+
+       for (i = 0; i < 8; i++)
+               ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
+
+       for (i = 0; i < 8; i++)
+               ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
+
+       ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
+       ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
+
+       for (i = 0; i < 24; i++)
+               ecc_sum += ecc_bit[i];
+
+       switch (ecc_sum) {
+       case 0:
+               /* Not reached because this function is not called if
+                  ECC values are equal */
+               return 0;
+
+       case 1:
+               /* Uncorrectable error */
+               DEBUG (MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
+               return -1;
+
+       case 12:
+               /* Correctable error */
+               find_byte = (ecc_bit[23] << 8) + 
+                           (ecc_bit[21] << 7) + 
+                           (ecc_bit[19] << 6) +
+                           (ecc_bit[17] << 5) +
+                           (ecc_bit[15] << 4) +
+                           (ecc_bit[13] << 3) +
+                           (ecc_bit[11] << 2) +
+                           (ecc_bit[9]  << 1) +
+                           ecc_bit[7];
+
+               find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
+
+               DEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at offset: %d, bit: %d\n", find_byte, find_bit);
+
+               page_data[find_byte] ^= (1 << find_bit);
+
+               return 0;
+       default:
+               if (isEccFF) {
+                       if (ecc_data2[0] == 0 && ecc_data2[1] == 0 && ecc_data2[2] == 0)
+                               return 0;
+               } 
+               DEBUG (MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
+               return -1;
+       }
+}
+
+static int omap_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+{
+       struct nand_chip *this;
+       int block_count = 0, i, r;
+
+       this = mtd->priv;
+       if (this->eccmode == NAND_ECC_HW12_2048)
+               block_count = 4;
+       else
+               block_count = 1;
+       for (i = 0; i < block_count; i++) {
+               if (memcmp(read_ecc, calc_ecc, 3) != 0) {
+                       r = omap_nand_compare_ecc(read_ecc, calc_ecc, dat);
+                       if (r < 0)
+                               return r;
+               }
+               read_ecc += 3;
+               calc_ecc += 3;
+               dat += 512;
+       }
+       return 0;
+}
+
+static void omap_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+       nand_write_reg(NND_RESET, 0x01);
+}
+
+static int omap_nand_scan_bbt(struct mtd_info *mtd)
+{
+       return 0;
+}
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+
+extern int mtdpart_setup(char *);
+
+static int __init add_dynamic_parts(struct mtd_info *mtd)
+{
+       static const char *part_parsers[] = { "cmdlinepart", NULL };
+       struct mtd_partition *parts;
+       const struct omap_flash_part_config *cfg;
+       char *part_str = NULL;
+       size_t part_str_len;
+       int c;
+
+       cfg = omap_get_var_config(OMAP_TAG_FLASH_PART, &part_str_len);
+       if (cfg != NULL) {
+               part_str = kmalloc(part_str_len + 1, GFP_KERNEL);
+               if (part_str == NULL)
+                       return -ENOMEM;
+               memcpy(part_str, cfg->part_table, part_str_len);
+               part_str[part_str_len] = '\0';
+               mtdpart_setup(part_str);
+       }
+       c = parse_mtd_partitions(omap_mtd, part_parsers, &parts, 0);
+       if (part_str != NULL) {
+               mtdpart_setup(NULL);
+               kfree(part_str);
+       }
+       if (c <= 0)
+               return -1;
+
+       add_mtd_partitions(mtd, parts, c);
+
+       return 0;
+}
+
+#else
+
+static inline int add_dynamic_parts(struct mtd_info *mtd)
+{
+       return -1;
+}
+
+#endif
+
+static inline int calc_psc(int ns, int cycle_ps)
+{
+       return (ns * 1000 + (cycle_ps - 1)) / cycle_ps;
+}
+
+static void set_psc_regs(int psc_ns, int psc1_ns, int psc2_ns)
+{
+       int psc[3], i;
+       unsigned long rate, ps;
+
+       rate = clk_get_rate(omap_nand_clk);
+       ps = 1000000000 / (rate / 1000);
+       psc[0] = calc_psc(psc_ns, ps);
+       psc[1] = calc_psc(psc1_ns, ps);
+       psc[2] = calc_psc(psc2_ns, ps);
+       for (i = 0; i < 3; i++) {
+               if (psc[i] == 0)
+                       psc[i] = 1;
+               else if (psc[i] > 256)
+                       psc[i] = 256;
+       }
+       nand_write_reg(NND_PSC_CLK, psc[0] - 1);
+       nand_write_reg(NND_PSC1_CLK, psc[1] - 1);
+       nand_write_reg(NND_PSC2_CLK, psc[2] - 1);
+       printk(KERN_INFO "omap-hw-nand: using PSC values %d, %d, %d\n", psc[0], psc[1], psc[2]);
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init omap_nand_init(void)
+{
+       struct nand_chip *this;
+       int err = 0;
+       u32 l;
+
+       omap_nand_clk = clk_get(NULL, "armper_ck");
+       BUG_ON(omap_nand_clk == NULL);
+       clk_use(omap_nand_clk);
+
+       l = nand_read_reg(NND_REVISION);        
+       printk(KERN_INFO "omap-hw-nand: OMAP NAND Controller rev. %d.%d\n", l>>4, l & 0xf);
+
+       /* Reset the NAND Controller */
+       nand_write_reg(NND_SYSCFG, 0x02);
+       while ((nand_read_reg(NND_SYSSTATUS) & 0x01) == 0);
+
+       /* No Prefetch, no postwrite, write prot & enable pairs disabled,
+          addres counter set to send 4 byte addresses to flash,
+          A8 is set not to be sent to flash (erase addre needs formatting),
+          choose little endian, enable 512 byte ECC logic,        
+        */
+       nand_write_reg(NND_CTRL, 0xFF01);
+
+       /* Allocate memory for MTD device structure and private data */
+       omap_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+       if (!omap_mtd) {
+               printk(KERN_WARNING "omap-hw-nand: Unable to allocate OMAP NAND MTD device structure.\n");
+               err = -ENOMEM;
+               goto free_clock;
+       }
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *) (&omap_mtd[1]);
+
+       /* Initialize structures */
+       memset((char *) omap_mtd, 0, sizeof(struct mtd_info));
+       memset((char *) this, 0, sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       omap_mtd->priv = this;
+       omap_mtd->name = "omap-nand";
+
+       /* Used from chip select and nand_command() */
+       this->read_byte = omap_nand_read_byte;
+       this->write_byte = omap_nand_write_byte;
+
+       this->select_chip = omap_nand_select_chip;
+       this->dev_ready = omap_nand_dev_ready;
+       this->chip_delay = 0;
+       this->eccmode = NAND_ECC_HW3_512; 
+       this->cmdfunc = omap_nand_command;
+       this->write_buf = omap_nand_write_buf;
+       this->read_buf = omap_nand_read_buf;
+       this->verify_buf = omap_nand_verify_buf;
+       this->calculate_ecc = omap_nand_calculate_ecc;
+       this->correct_data = omap_nand_correct_data;
+       this->enable_hwecc = omap_nand_enable_hwecc;
+       this->scan_bbt = omap_nand_scan_bbt;
+
+       nand_write_reg(NND_PSC_CLK, 10);
+       /* Scan to find existance of the device */
+       if (nand_scan(omap_mtd, 1)) {
+               err = -ENXIO;
+               goto out_mtd;
+       }
+
+       set_psc_regs(25, 15, 35);
+       if (this->page_shift == 11) {
+               this->cmdfunc = omap_nand_command_lp;
+               l = nand_read_reg(NND_CTRL);
+               l |= 1 << 4; /* Set the A8 bit in CTRL reg */
+               nand_write_reg(NND_CTRL, l);
+               this->eccmode = NAND_ECC_HW12_2048;
+               this->eccsteps = 1;
+               this->eccsize = 2048;
+               this->eccbytes = 12;
+               omap_mtd->eccsize = 2048;
+               nand_write_reg(NND_ECC_SELECT, 6);
+       }
+
+       this->options |= NAND_NO_AUTOINCR;
+
+       err = add_dynamic_parts(omap_mtd);
+       if (err < 0) {
+               printk(KERN_ERR "omap-hw-nand: no partitions defined\n");
+               err = -ENODEV;
+               nand_release(omap_mtd);
+               goto out_mtd;
+       }
+       /* init completed */
+       return 0;
+out_mtd:
+       kfree(omap_mtd);
+free_clock:
+       clk_put(omap_nand_clk);
+       return err;
+}
+
+module_init(omap_nand_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit omap_nand_cleanup (void)
+{
+       clk_unuse(omap_nand_clk);
+       clk_put(omap_nand_clk);
+       nand_release(omap_mtd);
+       kfree(omap_mtd);
+}
+
+module_exit(omap_nand_cleanup);
+
diff --git a/drivers/mtd/nand/omap-nand-flash.c b/drivers/mtd/nand/omap-nand-flash.c
new file mode 100644 (file)
index 0000000..d697296
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ *  drivers/mtd/nand/omap-nand-flash.c
+ *
+ *  Copyright (c) 2004 Texas Instruments
+ *  Jian Zhang <jzhang@ti.com>
+ *  Copyright (c) 2004 David Brownell
+ *
+ *  Derived from drivers/mtd/autcpu12.c
+ *
+ *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
+ *
+ * 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.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   TI H3/H2  boards. It supports 16-bit 32MiB Samsung k9f5616 chip.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tc.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+#define H3_NAND_RB_GPIO_PIN            10
+#define H2_NAND_RB_GPIO_PIN            62
+#define P2_NAND_RB_GPIO_PIN            62
+#define NETSTAR_NAND_RB_GPIO_PIN        1
+/*
+ * MTD structure for H3 board
+ */
+static struct mtd_info *omap_nand_mtd = NULL;
+
+static void __iomem *omap_nand_flash_base;
+
+/*
+ * Define partitions for flash devices
+ */
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition static_partition[] = {
+       { .name = "Booting Image",
+         .offset =     0,
+         .size = 64 * 1024,
+         .mask_flags = MTD_WRITEABLE  /* force read-only */
+       },
+       { .name = "U-Boot",
+         .offset =     MTDPART_OFS_APPEND,
+         .size = 256 * 1024,
+          .mask_flags = MTD_WRITEABLE  /* force read-only */
+       },
+       { .name = "U-Boot Environment",
+         .offset =     MTDPART_OFS_APPEND,
+         .size = 192 * 1024
+       },
+       { .name = "Kernel",
+         .offset =     MTDPART_OFS_APPEND,
+         .size = 2 * SZ_1M
+       },
+       { .name = "File System",
+         .size = MTDPART_SIZ_FULL,
+         .offset =     MTDPART_OFS_APPEND,
+       },
+};
+
+const char *part_probes[] = { "cmdlinepart", NULL,  };
+
+#endif
+
+/* H2/H3 maps two address LSBs to CLE and ALE; MSBs make CS_2B */
+#define        MASK_CLE        0x02
+#define        MASK_ALE        0x04
+
+
+/* 
+ *     hardware specific access to control-lines
+*/
+static void omap_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+       struct nand_chip *this = mtd->priv;
+       u32 IO_ADDR_W = (u32) this->IO_ADDR_W;
+
+       IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
+       switch(cmd){
+               case NAND_CTL_SETCLE: IO_ADDR_W |= MASK_CLE; break;
+               case NAND_CTL_SETALE: IO_ADDR_W |= MASK_ALE; break;
+       }
+       this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
+}
+
+/*
+ *     chip busy R/B detection
+ */
+static int omap_nand_ready(struct mtd_info *mtd)
+{
+       if (machine_is_omap_h3())
+               return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
+       if (machine_is_omap_h2())
+               return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
+       if (machine_is_omap_perseus2())
+               return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
+       if (machine_is_netstar())
+               return omap_get_gpio_datain(NETSTAR_NAND_RB_GPIO_PIN);
+       return 0;
+}
+
+/* Scan to find existance of the device at omap_nand_flash_base.
+   This also allocates oob and data internal buffers */
+static int __init probe_nand_chip(void)
+{
+        struct nand_chip *this;
+
+        this = (struct nand_chip *) (&omap_nand_mtd[1]);
+       
+       /* Initialize structures */
+        memset((char *) this, 0, sizeof(struct nand_chip));
+        
+       this->IO_ADDR_R = omap_nand_flash_base;
+        this->IO_ADDR_W = omap_nand_flash_base;
+        this->options = NAND_SAMSUNG_LP_OPTIONS;
+        this->hwcontrol = omap_nand_hwcontrol;
+        this->eccmode = NAND_ECC_SOFT;
+
+        /* try 16-bit chip first */
+       this->options |= NAND_BUSWIDTH_16;
+        if (nand_scan (omap_nand_mtd, 1)) {
+               if (machine_is_omap_h3()) 
+                       return -ENXIO;
+
+               /* then try 8-bit chip for H2 */
+               memset((char *) this, 0, sizeof(struct nand_chip));
+               this->IO_ADDR_R = omap_nand_flash_base;
+               this->IO_ADDR_W = omap_nand_flash_base;
+               this->options = NAND_SAMSUNG_LP_OPTIONS;
+               this->hwcontrol = omap_nand_hwcontrol;
+               this->eccmode = NAND_ECC_SOFT;
+                if (nand_scan (omap_nand_mtd, 1)) {
+                        return -ENXIO;
+                }
+        }
+
+       return 0;
+}
+
+static char nand1_name [] = "nand";
+
+/*
+ * Main initialization routine
+ */
+int __init omap_nand_init (void)
+{
+       struct nand_chip *this;
+       struct mtd_partition *dynamic_partition = 0;
+       int err = 0;
+       int nandboot = 0;
+
+       if (!(machine_is_omap_h2() || machine_is_omap_h3() || machine_is_netstar() || machine_is_omap_perseus2()))
+               return -ENODEV;
+
+       /* Allocate memory for MTD device structure and private data */
+       omap_nand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
+                               GFP_KERNEL);
+       if (!omap_nand_mtd) {
+               printk (KERN_WARNING "Unable to allocate NAND MTD device structure.\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *) (&omap_nand_mtd[1]);
+
+       /* Initialize structures */
+       memset((char *) omap_nand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       omap_nand_mtd->priv = this;
+
+       if (machine_is_omap_h2() || machine_is_omap_perseus2()) {
+               /* FIXME on H2, R/B needs M7_1610_GPIO62 ... */
+               this->chip_delay = 15;
+               omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+               omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+       } else if (machine_is_omap_h3()) {
+               if (omap_request_gpio(H3_NAND_RB_GPIO_PIN) != 0) {
+                       printk(KERN_ERR "NAND: Unable to get GPIO pin for R/B, use delay\n");
+                       /* 15 us command delay time */
+                       this->chip_delay = 15;
+               } else {
+                       /* GPIO10 for input. it is in GPIO1 module */
+                       omap_set_gpio_direction(H3_NAND_RB_GPIO_PIN, 1);
+               
+                       /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
+                       /* GPIO10 pullup/down register, Enable pullup on GPIO10 */
+                       omap_cfg_reg(V2_1710_GPIO10);
+
+                       this->dev_ready = omap_nand_ready;
+               }
+       } else if (machine_is_netstar()) {
+               if (omap_request_gpio(NETSTAR_NAND_RB_GPIO_PIN) != 0) {
+                       printk(KERN_ERR "NAND: Unable to get GPIO pin for R/B, use delay\n");
+                       /* 15 us command delay time */
+                       this->chip_delay = 15;
+               } else {
+                       omap_set_gpio_direction(NETSTAR_NAND_RB_GPIO_PIN, 1);
+                       this->dev_ready = omap_nand_ready;
+               }
+       }
+
+        /* try the first address */
+       omap_nand_flash_base = ioremap(OMAP_NAND_FLASH_START1, SZ_4K);
+       omap_nand_mtd->name = nand1_name;
+       if (probe_nand_chip()){
+               nandboot = 1;
+               /* try the second address */
+               iounmap(omap_nand_flash_base);
+               omap_nand_flash_base = ioremap(OMAP_NAND_FLASH_START2, SZ_4K);
+               if (probe_nand_chip()){
+                       iounmap(omap_nand_flash_base);
+                        err = -ENXIO;
+                        goto out_mtd;
+               }
+       }
+
+       /* Register the partitions */
+       switch(omap_nand_mtd->size) {
+       case SZ_128M:
+               if (!(machine_is_netstar()))
+                       goto out_unsupported;
+               /* fall through */
+       case SZ_64M:
+               if (!(machine_is_netstar() || machine_is_omap_perseus2()))
+                       goto out_unsupported;
+               /* fall through */
+       case SZ_32M:
+#ifdef CONFIG_MTD_PARTITIONS
+               err = parse_mtd_partitions(omap_nand_mtd, part_probes,
+                                       &dynamic_partition, 0);
+               if (err > 0)
+                       err = add_mtd_partitions(omap_nand_mtd,
+                                       dynamic_partition, err);
+               else if (nandboot)
+                       err = add_mtd_partitions(omap_nand_mtd,
+                                       static_partition,
+                                       ARRAY_SIZE(static_partition));
+               else
+#endif
+                       err = add_mtd_device(omap_nand_mtd);
+               if (err)
+                       goto out_buf;
+               break;
+out_unsupported:
+       default:
+               printk(KERN_WARNING "Unsupported NAND device\n");
+               err = -ENXIO;
+               goto out_buf;
+       }
+
+       goto out;
+
+out_buf:
+       nand_release (omap_nand_mtd);
+       if (this->dev_ready) {
+               if (machine_is_omap_h2())
+                       omap_free_gpio(H2_NAND_RB_GPIO_PIN);
+               else if (machine_is_omap_perseus2())
+                       omap_free_gpio(P2_NAND_RB_GPIO_PIN);
+               else if (machine_is_omap_h3())
+                       omap_free_gpio(H3_NAND_RB_GPIO_PIN);
+               else if (machine_is_netstar())
+                       omap_free_gpio(NETSTAR_NAND_RB_GPIO_PIN);
+       }
+       iounmap(omap_nand_flash_base);
+
+out_mtd:
+       kfree (omap_nand_mtd);
+out:
+       return err;
+}
+
+module_init(omap_nand_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit omap_nand_cleanup (void)
+{
+        struct nand_chip *this = omap_nand_mtd->priv;
+       if (this->dev_ready) {
+               if (machine_is_omap_h2())
+                       omap_free_gpio(H2_NAND_RB_GPIO_PIN);
+               else if (machine_is_omap_h2())
+                       omap_free_gpio(H2_NAND_RB_GPIO_PIN);
+               else if (machine_is_omap_h3())
+                       omap_free_gpio(H3_NAND_RB_GPIO_PIN);
+               else if (machine_is_netstar())
+                       omap_free_gpio(NETSTAR_NAND_RB_GPIO_PIN);
+       }
+
+       /* nand_release frees MTD partitions, MTD structure
+          and nand internal buffers*/
+       nand_release (omap_nand_mtd);
+       kfree (omap_nand_mtd);
+       iounmap(omap_nand_flash_base);
+}
+
+module_exit(omap_nand_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jian Zhang <jzhang@ti.com>");
+MODULE_DESCRIPTION("Glue layer for NAND flash on H2/H3 boards");
index d54156f11e61a3cb043bc20f25fa48fde0fc217f..b200c50a22933f85e5b47268ca2fbad201217883 100644 (file)
@@ -341,6 +341,13 @@ config TOSHIBA_FIR
          To compile it as a module, choose M here: the module will be called
          donauboe.
 
+config OMAP1610_IR
+        tristate "OMAP1610 IrDA(SIR/MIR/FIR)"
+       depends on IRDA && ARCH_OMAP
+       select GPIOEXPANDER_OMAP if MACH_OMAP_H3
+        help
+          Say Y here if you want to build support for the Omap1610 IR.
+
 config AU1000_FIR
        tristate "Alchemy Au1000 SIR/FIR"
        depends on MIPS_AU1000 && IRDA
index e7a8b7f7f5ddf7570117d9a59b3700c550f8c2da..7db79a2322254dfa5982fddc614c93d492c333f7 100644 (file)
@@ -43,6 +43,8 @@ obj-$(CONFIG_OLD_BELKIN_DONGLE)       += old_belkin-sir.o
 obj-$(CONFIG_MCP2120_DONGLE)   += mcp2120-sir.o
 obj-$(CONFIG_ACT200L_DONGLE)   += act200l-sir.o
 obj-$(CONFIG_MA600_DONGLE)     += ma600-sir.o
+obj-$(CONFIG_OMAP1610_IR)       += omap1610-ir.o
+
 
 # The SIR helper module
 sir-dev-objs := sir_core.o sir_dev.o sir_dongle.o sir_kthread.o
diff --git a/drivers/net/irda/omap1610-ir.c b/drivers/net/irda/omap1610-ir.c
new file mode 100644 (file)
index 0000000..8d503ba
--- /dev/null
@@ -0,0 +1,994 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *
+ *     Infra-red driver for the OMAP1610-H2 and OMAP1710-H3 Platforms
+ *          (SIR/MIR/FIR modes)
+ *          (based on omap-sir.c)
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *        source@mvista.com
+ * 
+ * Copyright 2004 Texas Instruments.
+ *
+ *  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.
+ *
+ Modifications:
+ Feb 2004, Texas Instruments
+ - Ported to 2.6 kernel (Feb 2004).
+ *
+ Apr 2004, Texas Instruments
+ - Added support for H3 (Apr 2004). 
+ Nov 2004, Texas Instruments
+ - Added support for Power Management.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/dma-mapping.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/serial.h>
+#include <asm/mach-types.h>
+#include <asm/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
+#include <linux/i2c.h>
+
+#ifdef CONFIG_MACH_OMAP_H3
+#include <asm/arch/gpioexpander.h>
+#endif
+
+#define SIR_MODE 0
+#define MIR_MODE 1
+#define FIR_MODE 2
+
+#define OMAP1610_H2_FIRSEL_GPIO 17
+
+static int rx_state = 0;       /* RX state for IOCTL */
+
+struct omap1610_irda {
+       unsigned char open;
+       int speed;              /* Current IrDA speed */
+       int newspeed;
+
+       struct net_device_stats stats;
+       struct irlap_cb *irlap;
+       struct qos_info qos;
+
+       int rx_dma_channel;
+       int tx_dma_channel;
+
+       dma_addr_t rx_buf_dma_phys;     /* Physical adress of RX DMA buffer */
+       dma_addr_t tx_buf_dma_phys;     /* Physical adress of TX DMA buffer */
+
+       void *rx_buf_dma_virt;  /* Virtual adress of RX DMA buffer */
+       void *tx_buf_dma_virt;  /* Virtual adress of TX DMA buffer */
+
+       struct device *dev;
+};
+
+#define OMAP_IRDA_DEBUG        0
+
+#if (OMAP_IRDA_DEBUG > 0)
+#define DBG(format, args...) printk(KERN_ERR "%s(): " format, __FUNCTION__, ## args);
+#define DBG_IRQ(format, args...) printk(KERN_ERR "%s(): " format, __FUNCTION__, ## args);
+#else
+#define DBG(format, args...)
+#define DBG_IRQ(format, args...)
+#endif
+
+#if (OMAP_IRDA_DEBUG > 1)
+#define __ECHO_IN printk(KERN_ERR "%s: enter\n",__FUNCTION__);
+#define __ECHO_OUT printk(KERN_ERR "%s: exit\n",__FUNCTION__);
+#else
+#define __ECHO_IN
+#define __ECHO_OUT
+#endif
+
+#ifdef OMAP1610_IR_HARDWARE_DEBUG_ENABLE
+#define HDBG_DELAY 200
+
+void hard_debug1(u16 i)
+{
+       for (; i; i--) {
+               omap_writew(0x2000,
+                           OMAP1610_GPIO1_BASE + OMAP1610_GPIO_CLEAR_DATAOUT);
+               udelay(HDBG_DELAY);
+
+               omap_writew(0x2000,
+                           OMAP1610_GPIO1_BASE + OMAP1610_GPIO_SET_DATAOUT);
+               udelay(HDBG_DELAY);
+       }
+}
+
+void hard_debug2(u16 i)
+{
+       for (; i; i--) {
+               omap_writew(0x8000,
+                           OMAP1610_GPIO1_BASE + OMAP1610_GPIO_CLEAR_DATAOUT);
+               udelay(HDBG_DELAY);
+
+               omap_writew(0x8000,
+                           OMAP1610_GPIO1_BASE + OMAP1610_GPIO_SET_DATAOUT);
+               udelay(HDBG_DELAY);
+       }
+}
+
+#define HDBG1(i) hard_debug1(i)
+#define HDBG2(i) hard_debug2(i)
+#else
+#define HDBG1(i)
+#define HDBG2(i)
+#endif
+
+/* forward declarations */
+
+extern void irda_device_setup(struct net_device *dev);
+extern void omap_stop_dma(int lch);
+static int omap1610_irda_set_speed(struct net_device *dev, int speed);
+
+static void omap1610_irda_start_rx_dma(struct omap1610_irda *si)
+{
+       /* Configure DMA */
+       omap_set_dma_src_params(si->rx_dma_channel, 0x3, 0x0, (unsigned long)UART3_RHR,
+                               0, 0);
+
+       omap_enable_dma_irq(si->rx_dma_channel, 0x01);
+
+       omap_set_dma_dest_params(si->rx_dma_channel, 0x0, 0x1,
+                                si->rx_buf_dma_phys,
+                                0, 0);
+
+       omap_set_dma_transfer_params(si->rx_dma_channel, 0x0, 4096, 0x1, 0x0, 0, 0);
+
+       omap_start_dma(si->rx_dma_channel);
+}
+
+static void omap1610_start_tx_dma(struct omap1610_irda *si, int size)
+{
+       __ECHO_IN;
+
+       /* Configure DMA */
+       omap_set_dma_dest_params(si->tx_dma_channel, 0x03, 0x0, (unsigned long)UART3_THR,
+                                       0, 0);
+       omap_enable_dma_irq(si->tx_dma_channel, 0x01);
+
+       omap_set_dma_src_params(si->tx_dma_channel, 0x0, 0x1,
+                               si->tx_buf_dma_phys,
+                               0, 0);
+
+       omap_set_dma_transfer_params(si->tx_dma_channel, 0x0, size, 0x1, 0x0, 0, 0);
+
+       HDBG1(1);
+
+       /* Start DMA */
+       omap_start_dma(si->tx_dma_channel);
+
+       HDBG1(1);
+
+       __ECHO_OUT;
+}
+
+/* DMA RX callback - normally, we should not go here, 
+   it calls only if something is going wrong
+ */
+
+static void omap1610_irda_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       struct net_device *dev = data;
+       struct omap1610_irda *si = dev->priv;
+
+       printk(KERN_ERR "RX Transfer error or very big frame \n");
+
+       /* Clear interrupts */
+       omap_readb(UART3_IIR);
+
+       si->stats.rx_frame_errors++;
+
+       omap_readb(UART3_RESUME);
+
+       /* Re-init RX DMA */
+       omap1610_irda_start_rx_dma(si);
+
+}
+
+/* DMA TX callback - calling when frame transfer has been finished */
+
+static void omap1610_irda_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       struct net_device *dev = data;
+       struct omap1610_irda *si = dev->priv;
+
+       __ECHO_IN;
+
+       /*Stop DMA controller */
+       omap_stop_dma(si->tx_dma_channel);
+
+       __ECHO_OUT;
+
+}
+
+/*
+ * Set the IrDA communications speed.
+ * Interrupt have to be disabled here.
+ */
+
+static int omap1610_irda_startup(struct net_device *dev)
+{
+       __ECHO_IN;
+
+       /* Enable UART3 clock and set UART3 to IrDA mode */
+       omap_writel(omap_readl(MOD_CONF_CTRL_0) | (1 << 31) | (1 << 15),
+                   MOD_CONF_CTRL_0);
+
+       if (machine_is_omap_h2()) {
+//              omap_cfg_reg(Y15_1610_GPIO17);
+               omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A);
+
+               omap_set_gpio_direction(OMAP1610_H2_FIRSEL_GPIO, 0);
+               omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 0);
+       }
+
+       omap_writeb(0x07, UART3_MDR1);  /* Put UART3 in reset mode */
+
+       /* Clear DLH and DLL */
+       omap_writeb(1 << 7, UART3_LCR);
+
+       omap_writeb(0, UART3_DLL);
+       omap_writeb(0, UART3_DLH);
+
+       omap_writeb(0xbf, UART3_LCR);
+
+       omap_writeb(1 << 4, UART3_EFR);
+
+       omap_writeb(1 << 7, UART3_LCR);
+
+       /* Enable access to UART3_TLR and UART3_TCR registers */
+       omap_writeb(1 << 6, UART3_MCR);
+
+       omap_writeb(0, UART3_SCR);
+
+       /* Set Rx trigger to 1 and Tx trigger to 1 */
+       omap_writeb(0, UART3_TLR);
+
+       /* Set LCR to 8 bits and 1 stop bit */
+       omap_writeb(0x03, UART3_LCR);
+
+       /* Clear RX and TX FIFO and enable FIFO */
+       /* Use DMA Req for transfers */
+
+       omap_writeb((1 << 2) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 6) | 1,
+                   UART3_FCR);
+
+       omap_writeb(0, UART3_MCR);
+
+       omap_writeb((1 << 7) | (1 << 6), UART3_SCR);
+
+       /* Enable UART3 SIR Mode,(Frame-length method to end frames) */
+       omap_writeb(1, UART3_MDR1);
+
+       /* Set Status FIFO trig to 1 */
+       omap_writeb(0, UART3_MDR2);
+
+       /* Enables RXIR input */
+       /* and disable TX underrun */
+       /* SEND_SIP pulse */
+
+       //   omap_writeb((1 << 7) | (1 << 6) | (1 << 4), UART3_ACREG);
+       omap_writeb((1 << 6) | (1 << 4), UART3_ACREG);
+
+       /* Enable EOF Interrupt only */
+       omap_writeb((1 << 7) | (1 << 5), UART3_IER);
+
+       /* Set Maximum Received Frame size to 2048 bytes */
+       omap_writeb(0x00, UART3_RXFLL);
+       omap_writeb(0x08, UART3_RXFLH);
+
+       omap_readb(UART3_RESUME);
+
+       __ECHO_OUT;
+
+       return 0;
+
+}
+
+static int omap1610_irda_shutdown(struct omap1610_irda *si)
+{
+       /* Disable all UART3 Interrupts */
+       omap_writeb(0, UART3_IER);
+
+       /* Disable UART3 and disable baud rate generator */
+       omap_writeb(0x07, UART3_MDR1);  /* Put UART3 in reset mode */
+
+       omap_writeb((1 << 5), UART3_ACREG);     /* set SD_MODE pin to high and Disable RX IR */
+
+       /* Clear DLH and DLL */
+       omap_writeb(1 << 7, UART3_LCR);
+       omap_writeb(0, UART3_DLL);
+       omap_writeb(0, UART3_DLH);
+
+       return 0;
+}
+
+static irqreturn_t
+omap1610_irda_irq(int irq, void *dev_id, struct pt_regs *hw_regs)
+{
+       struct net_device *dev = dev_id;
+       struct omap1610_irda *si = dev->priv;
+       struct sk_buff *skb;
+
+       u8 status;
+       int w = 0;
+
+       __ECHO_IN;
+
+       /* Clear EOF interrupt */
+       status = omap_readb(UART3_IIR);
+
+       if (status & (1 << 5)) {
+               u8 mdr2 = omap_readb(UART3_MDR2);
+               HDBG1(2);
+               if (mdr2 & 1)
+                       printk(KERN_ERR "IRDA Buffer underrun error");
+
+               si->stats.tx_packets++;
+
+               if (si->newspeed) {
+                       omap1610_irda_set_speed(dev, si->newspeed);
+                       si->newspeed = 0;
+               }
+
+               netif_wake_queue(dev);
+
+               if (!(status & 0x80))
+                       return IRQ_HANDLED;
+       }
+
+       /* Stop DMA and if there are no errors, send frame to upper layer */
+
+       omap_stop_dma(si->rx_dma_channel);
+
+       status = omap_readb(UART3_SFLSR);       /* Take a frame status */
+
+       if (status != 0) {      /* Bad frame? */
+               si->stats.rx_frame_errors++;
+               omap_readb(UART3_RESUME);
+       } else {
+               /* We got a frame! */
+               skb = alloc_skb(4096, GFP_ATOMIC);
+
+               if (!skb) {
+                       printk(KERN_ERR "omap_sir: out of memory for RX SKB\n");
+                       return IRQ_HANDLED;
+               }
+               /*
+                * Align any IP headers that may be contained
+                * within the frame.
+                */
+
+               skb_reserve(skb, 1);
+
+               w = OMAP_DMA_CDAC_REG(si->rx_dma_channel);
+               w -= OMAP1_DMA_CDSA_L_REG(si->rx_dma_channel);
+
+               if (si->speed != 4000000) {
+                       memcpy(skb_put(skb, w - 2), si->rx_buf_dma_virt, w - 2);        /* Copy DMA buffer to skb */
+               } else {
+                       memcpy(skb_put(skb, w - 4), si->rx_buf_dma_virt, w - 4);        /* Copy DMA buffer to skb */
+               }
+
+               skb->dev = dev;
+               skb->mac.raw = skb->data;
+               skb->protocol = htons(ETH_P_IRDA);
+               si->stats.rx_packets++;
+               si->stats.rx_bytes += skb->len;
+               netif_receive_skb(skb); /* Send data to upper level */
+       }
+
+       /* Re-init RX DMA */
+       omap1610_irda_start_rx_dma(si);
+
+       dev->last_rx = jiffies;
+
+       __ECHO_OUT;
+
+       return IRQ_HANDLED;
+}
+
+static int omap1610_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct omap1610_irda *si = dev->priv;
+       int speed = irda_get_next_speed(skb);
+       int mtt = irda_get_mtt(skb);
+       int xbofs = irda_get_next_xbofs(skb);
+
+       __ECHO_IN;
+
+       /*
+        * Does this packet contain a request to change the interface
+        * speed?  If so, remember it until we complete the transmission
+        * of this frame.
+        */
+       if (speed != si->speed && speed != -1)
+               si->newspeed = speed;
+
+       if (xbofs) {
+               /* Set number of addtional BOFS */
+               omap_writeb(xbofs + 1, UART3_EBLR);
+       }
+
+       /*
+        * If this is an empty frame, we can bypass a lot.
+        */
+       if (skb->len == 0) {
+               if (si->newspeed) {
+                       si->newspeed = 0;
+                       omap1610_irda_set_speed(dev, speed);
+               }
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
+       netif_stop_queue(dev);
+
+       /* Copy skb data to DMA buffer */
+
+       memcpy(si->tx_buf_dma_virt, skb->data, skb->len);
+
+       si->stats.tx_bytes += skb->len;
+
+       /* Set frame length */
+
+       omap_writeb((skb->len & 0xff), UART3_TXFLL);
+       omap_writeb((skb->len >> 8), UART3_TXFLH);
+
+       if (mtt > 1000)
+               mdelay(mtt / 1000);
+       else
+               udelay(mtt);
+
+       /* Start TX DMA transfer */
+
+       omap1610_start_tx_dma(si, skb->len);
+
+       /* We can free skb now because it's already in DMA buffer */
+
+       dev_kfree_skb(skb);
+
+       dev->trans_start = jiffies;
+
+       __ECHO_OUT;
+
+       return 0;
+}
+
+static int
+omap1610_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+{
+       struct if_irda_req *rq = (struct if_irda_req *)ifreq;
+       struct omap1610_irda *si = dev->priv;
+       int ret = -EOPNOTSUPP;
+
+       __ECHO_IN;
+
+       switch (cmd) {
+       case SIOCSBANDWIDTH:
+               if (capable(CAP_NET_ADMIN)) {
+                       /*
+                        * We are unable to set the speed if the
+                        * device is not running.
+                        */
+                       if (si->open) {
+                               ret =
+                                   omap1610_irda_set_speed(dev,
+                                                           rq->ifr_baudrate);
+                       } else {
+                               printk
+                                   (KERN_ERR
+                                    "omap_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");
+                               ret = 0;
+                       }
+               }
+               break;
+
+       case SIOCSMEDIABUSY:
+               ret = -EPERM;
+               if (capable(CAP_NET_ADMIN)) {
+                       irda_device_set_media_busy(dev, TRUE);
+                       ret = 0;
+               }
+               break;
+
+       case SIOCGRECEIVING:
+               rq->ifr_receiving = rx_state;
+               break;
+
+       default:
+               break;
+       }
+
+       __ECHO_OUT;
+
+       return ret;
+}
+
+static struct net_device_stats *omap1610_irda_stats(struct net_device *dev)
+{
+       struct omap1610_irda *si = dev->priv;
+       return &si->stats;
+}
+
+static int omap1610_irda_start(struct net_device *dev)
+{
+       struct omap1610_irda *si = dev->priv;
+       int err;
+       unsigned long flags = 0;
+
+#ifdef CONFIG_MACH_OMAP_H3
+       u8 ioExpanderVal = 0;
+#endif
+
+       __ECHO_IN;
+       si->speed = 9600;
+
+       err = request_irq(dev->irq, omap1610_irda_irq, 0, dev->name, dev);
+       if (err)
+               goto err_irq;
+
+       /*
+        * The interrupt must remain disabled for now.
+        */
+
+       disable_irq(dev->irq);
+
+       /*  Request DMA channels for IrDA hardware */
+
+       if (omap_request_dma(OMAP_DMA_UART3_RX, "IrDA Rx DMA",
+                            (void *)omap1610_irda_rx_dma_callback,
+                            dev, &(si->rx_dma_channel))) {
+               printk(KERN_ERR "Failed to request IrDA Rx DMA \n");
+               goto err_irq;
+       }
+
+       if (omap_request_dma(OMAP_DMA_UART3_TX, "IrDA Tx DMA",
+                            (void *)omap1610_irda_tx_dma_callback,
+                            dev, &(si->tx_dma_channel))) {
+               printk(KERN_ERR "Failed to request IrDA Tx DMA \n");
+               goto err_irq;
+       }
+
+       /* Allocate TX and RX buffers for DMA channels */
+
+       si->rx_buf_dma_virt =
+           dma_alloc_coherent(NULL, 4096, &(si->rx_buf_dma_phys), flags);
+
+       si->tx_buf_dma_virt =
+           dma_alloc_coherent(NULL, 4096, &(si->tx_buf_dma_phys), flags);
+
+       /*
+        * Setup the serial port for the specified config.
+        */
+
+#ifdef CONFIG_MACH_OMAP_H3
+
+       if ((err = read_gpio_expa(&ioExpanderVal, 0x26))) {
+               printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+               return err;
+       }
+
+       ioExpanderVal |= 0x40;  /* 'P6' Enable IRDA_TX and IRDA_RX */
+
+       if ((err = write_gpio_expa(ioExpanderVal, 0x26))) {
+               printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+               return err;
+       }
+#endif
+       err = omap1610_irda_startup(dev);
+
+       if (err)
+               goto err_startup;
+
+       omap1610_irda_set_speed(dev, si->speed = 9600);
+
+       /*
+        * Open a new IrLAP layer instance.
+        */
+
+       si->irlap = irlap_open(dev, &si->qos, "omap_sir");
+
+       err = -ENOMEM;
+       if (!si->irlap)
+               goto err_irlap;
+
+       /* Now enable the interrupt and start the queue  */
+       si->open = 1;
+
+       /* Start RX DMA */
+
+       omap1610_irda_start_rx_dma(si);
+
+       enable_irq(dev->irq);
+       netif_start_queue(dev);
+
+       __ECHO_OUT;
+
+       return 0;
+
+      err_irlap:
+       si->open = 0;
+       omap1610_irda_shutdown(si);
+      err_startup:
+      err_irq:
+       free_irq(dev->irq, dev);
+       return err;
+}
+
+static int omap1610_irda_stop(struct net_device *dev)
+{
+       struct omap1610_irda *si = dev->priv;
+
+       __ECHO_IN;
+
+       disable_irq(dev->irq);
+
+       netif_stop_queue(dev);
+
+       omap_free_dma(si->rx_dma_channel);
+       omap_free_dma(si->tx_dma_channel);
+
+       dma_free_coherent(NULL, 4096, si->rx_buf_dma_virt, si->rx_buf_dma_phys);
+       dma_free_coherent(NULL, 4096, si->tx_buf_dma_virt, si->tx_buf_dma_phys);
+
+       omap1610_irda_shutdown(si);
+
+       /* Stop IrLAP */
+       if (si->irlap) {
+               irlap_close(si->irlap);
+               si->irlap = NULL;
+       }
+
+       si->open = 0;
+
+       /*
+        * Free resources
+        */
+
+       free_irq(dev->irq, dev);
+
+       __ECHO_OUT;
+
+       return 0;
+}
+
+#ifdef CONFIG_MACH_OMAP_H3
+
+static void set_h3_gpio_expa(u8 FIR_SEL, u8 IrDA_INVSEL)
+{
+       u8 ioExpanderVal = 0;
+
+       if (read_gpio_expa(&ioExpanderVal, 0x27) != 0) {
+               printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+               return;
+       }
+
+       ioExpanderVal &= ~0x03;
+       ioExpanderVal |= FIR_SEL << 1;
+       ioExpanderVal |= IrDA_INVSEL << 0;
+
+       if (write_gpio_expa(ioExpanderVal, 0x27) != 0) {
+               printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+               return;
+       }
+       if (read_gpio_expa(&ioExpanderVal, 0x27) != 0) {
+               printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+               return;
+       }
+}
+
+int which_speed;
+
+static void set_h3_gpio_expa_handler(void *data)
+{
+       int *mode = data;
+
+       if (*mode == SIR_MODE)
+               set_h3_gpio_expa(0, 1);
+       else if (*mode == MIR_MODE)
+               set_h3_gpio_expa(1, 1);
+       else if (*mode == FIR_MODE)
+               set_h3_gpio_expa(1, 1);
+}
+
+DECLARE_WORK(set_h3_gpio_expa_work, &set_h3_gpio_expa_handler, &which_speed);
+
+static inline void set_h3_irda_mode(int mode)
+{
+       cancel_delayed_work(&set_h3_gpio_expa_work);
+       which_speed = mode;
+       schedule_work(&set_h3_gpio_expa_work);
+}
+#else
+#define set_h3_irda_mode(x)
+#endif
+
+static int omap1610_irda_set_speed(struct net_device *dev, int speed)
+{
+       struct omap1610_irda *si = dev->priv;
+       int divisor;
+
+       __ECHO_IN;
+
+       /* Set IrDA speed */
+       if (speed <= 115200) {
+               /* SIR mode */
+               if (machine_is_omap_h2()) {
+                       omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 0);
+               }
+
+               if (machine_is_omap_h3())
+                       set_h3_irda_mode(SIR_MODE);
+
+               printk("Set SIR Mode! Speed: %d\n", speed);
+
+               omap_writeb(1, UART3_MDR1);     /* Set SIR mode */
+
+               omap_writeb(1, UART3_EBLR);
+
+               divisor = 48000000 / (16 * speed);      /* Base clock 48 MHz */
+
+               HDBG2(1);
+               omap_writeb(1 << 7, UART3_LCR);
+
+               omap_writeb((divisor & 0xFF), UART3_DLL);
+
+               omap_writeb((divisor >> 8), UART3_DLH);
+
+               omap_writeb(0x03, UART3_LCR);
+
+               omap_writeb(0, UART3_MCR);
+
+               HDBG2(1);
+
+       } else if (speed <= 1152000) {
+               /* MIR mode */
+               printk("Set MIR Mode! Speed: %d\n", speed);
+
+               omap_writeb((1 << 2) | (1 << 6), UART3_MDR1);   /* Set MIR mode with 
+                                                                  SIP after each frame */
+
+               omap_writeb(2, UART3_EBLR);
+
+               divisor = 48000000 / (41 * speed);      /* Base clock 48 MHz */
+
+               omap_writeb(1 << 7, UART3_LCR);
+
+               omap_writeb((divisor & 0xFF), UART3_DLL);
+
+               omap_writeb((divisor >> 8), UART3_DLH);
+
+               omap_writeb(0x03, UART3_LCR);
+
+               if (machine_is_omap_h2())
+                       omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 1);
+
+               if (machine_is_omap_h3())
+                       set_h3_irda_mode(MIR_MODE);
+
+       } else {
+               /* FIR mode */
+
+               printk("Set FIR Mode! Speed: %d\n", speed);
+
+               omap_writeb((1 << 2) | (1 << 6) | 1, UART3_MDR1);       /* Set FIR mode
+                                                                          with SIP after each frame */
+               if (machine_is_omap_h2())
+                       omap_set_gpio_dataout(OMAP1610_H2_FIRSEL_GPIO, 1);
+
+               if (machine_is_omap_h3())
+                       set_h3_irda_mode(FIR_MODE);
+       }
+
+       si->speed = speed;
+
+       __ECHO_OUT;
+
+       return 0;
+
+}
+
+#ifdef CONFIG_PM
+/*
+ * Suspend the IrDA interface.
+ */
+static int omap1610_irda_suspend(struct device *_dev, u32 state, u32 level)
+{
+       struct net_device *dev = dev_get_drvdata(_dev);
+       struct omap1610_irda *si = dev->priv;
+
+       if (!dev || level != SUSPEND_DISABLE)
+               return 0;
+
+       if (si->open) {
+               /*
+                * Stop the transmit queue
+                */
+               netif_device_detach(dev);
+               disable_irq(dev->irq);
+               omap1610_irda_shutdown(si);
+       }
+       return 0;
+}
+
+/*
+ * Resume the IrDA interface.
+ */
+static int omap1610_irda_resume(struct device *_dev, u32 level)
+{
+       struct net_device *dev = dev_get_drvdata(_dev);
+       struct omap1610_irda *si= dev->priv;
+
+       if (!dev || level != RESUME_ENABLE)
+               return 0;
+
+       if (si->open) {
+               /*
+                * If we missed a speed change, initialise at the new speed
+                * directly.  It is debatable whether this is actually
+                * required, but in the interests of continuing from where
+                * we left off it is desireable.  The converse argument is
+                * that we should re-negotiate at 9600 baud again.
+                */
+               if (si->newspeed) {
+                       si->speed = si->newspeed;
+                       si->newspeed = 0;
+               }
+
+               omap1610_irda_startup(dev);
+               omap1610_irda_set_speed(dev, si->speed);
+               enable_irq(dev->irq);
+
+               /*
+                * This automatically wakes up the queue
+                */
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+#else
+#define omap1610_irda_suspend  NULL
+#define omap1610_irda_resume   NULL
+#endif
+
+static int omap1610_irda_probe(struct device *_dev)
+{
+       struct platform_device *pdev = to_platform_device(_dev);
+       struct net_device *dev;
+       struct omap1610_irda *si;
+       unsigned int baudrate_mask;
+       int err = 0;
+
+       dev = alloc_irdadev(sizeof(struct omap1610_irda));
+       if (!dev)
+               goto err_mem_1;
+
+       si = dev->priv;
+       si->dev = &pdev->dev;
+       dev->hard_start_xmit = omap1610_irda_hard_xmit;
+       dev->open = omap1610_irda_start;
+       dev->stop = omap1610_irda_stop;
+       dev->do_ioctl = omap1610_irda_ioctl;
+       dev->get_stats = omap1610_irda_stats;
+       dev->irq = INT_UART3;
+
+       irda_init_max_qos_capabilies(&si->qos);
+
+       /*
+        *  OMAP1610  supports SIR, MIR, FIR modes,
+        *  but actualy supported modes depend on hardware implementation.
+        *  OMAP1610 Innovator supports only SIR and 
+        *  OMAP1610 H2 supports both SIR and FIR
+        */
+
+       baudrate_mask =
+           IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 | IR_576000 |
+           IR_1152000;
+
+       if (machine_is_omap_h2() || machine_is_omap_h3()) {
+
+               baudrate_mask |= (IR_4000000 << 8);
+       }
+
+       si->qos.baud_rate.bits &= baudrate_mask;
+       si->qos.min_turn_time.bits = 7;
+
+       irda_qos_bits_to_value(&si->qos);
+
+       err = register_netdev(dev);
+       if (!err)
+               dev_set_drvdata(&pdev->dev, dev);
+       else 
+               free_netdev(dev);
+
+      err_mem_1:
+       return err;
+}
+
+static int omap1610_irda_remove(struct device *_dev)
+{
+       struct net_device *dev = dev_get_drvdata(_dev);
+       
+#ifdef CONFIG_MACH_OMAP_H3
+       if (machine_is_omap_h3())
+               cancel_delayed_work(&set_h3_gpio_expa_work);
+#endif
+       if (dev) {
+               unregister_netdev(dev);
+               free_netdev(dev);
+       }
+       return 0;
+}
+
+static struct device_driver omap1610ir_driver = {
+       .name = "omap1610-ir",
+       .bus = &platform_bus_type,
+       .probe = omap1610_irda_probe,
+       .remove = omap1610_irda_remove,
+       .suspend = omap1610_irda_suspend,
+       .resume = omap1610_irda_resume,
+};
+
+static int __init omap1610_irda_init(void)
+{
+       return driver_register(&omap1610ir_driver);
+
+}
+
+static void __exit omap1610_irda_exit(void)
+{
+       driver_unregister(&omap1610ir_driver);
+}
+
+module_init(omap1610_irda_init);
+module_exit(omap1610_irda_exit);
+
+MODULE_AUTHOR("MontaVista");
+MODULE_DESCRIPTION("OMAP IrDA Driver");
+MODULE_LICENSE("GPL");
+
index 74d5f1a6fdea262919736ebd9c86f45cd05d0a6e..56dbaa09c112f0c2ada5941e0cdd4db90c518684 100644 (file)
@@ -495,6 +495,11 @@ static inline void  smc_rcv(struct net_device *dev)
                dev->name, packet_number, status,
                packet_len, packet_len);
 
+       if (unlikely(packet_len == 0 && !(status & RS_ERRORS))) {
+               printk(KERN_ERR "%s: bad memory timings: rxlen %u status %x\n",
+                       dev->name, packet_len, status);
+               status |= RS_TOOSHORT;
+       }
        back:
        if (unlikely(packet_len < 6 || status & RS_ERRORS)) {
                if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) {
index 817f200742c37132b4982bb0a333ebe76096fcb8..0846892ff7a17d94616637cb3309f6280abac742 100644 (file)
@@ -188,6 +188,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define        SMC_IRQ_TRIGGER_TYPE (( \
                   machine_is_omap_h2() \
                || machine_is_omap_h3() \
+               || machine_is_omap_h4() \
                || (machine_is_omap_innovator() && !cpu_is_omap1510()) \
        ) ? IRQT_FALLING : IRQT_RISING)
 
index 47b5ade95bde5ae8093997c208f79ed242a4aaa7..dfb18c82fdff849f0b62064d380760a01395c891 100644 (file)
@@ -121,7 +121,8 @@ static int omap_cf_get_status(struct pcmcia_socket *s, u_int *sp)
 
                *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
                cf = container_of(s, struct omap_cf_socket, socket);
-               s->irq.AssignedIRQ = cf->irq;
+               s->irq.AssignedIRQ = 0;
+               s->pci_irq = cf->irq;
        } else
                *sp = 0;
        return 0;
@@ -320,7 +321,6 @@ static int __devexit omap_cf_remove(struct device *dev)
        struct omap_cf_socket *cf = dev_get_drvdata(dev);
 
        cf->active = 0;
-       pcmcia_unregister_socket(&cf->socket);
        del_timer_sync(&cf->timer);
        iounmap((void __iomem *) cf->socket.io_offset);
        release_mem_region(cf->phys_cf, SZ_8K);
index 98820603e75fd2a4a7b27206817744d60c10f833..2a609289b74262c27b914635cf859a37576bb1d0 100644 (file)
@@ -1347,7 +1347,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r
 
        DEBUG_INTR("end.\n");
 
-       return IRQ_RETVAL(handled);
+       //return IRQ_RETVAL(handled);
+       return IRQ_HANDLED;     /* FIXME: iir status not ready on 1510 */
 }
 
 /*
@@ -1863,6 +1864,17 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
                serial_outp(up, UART_EFR, efr);
        }
 
+#ifdef CONFIG_ARCH_OMAP15XX
+       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+       if (cpu_is_omap1510() && is_omap_port((unsigned int)up->port.membase)) {
+               if (baud == 115200) {
+                       quot = 1;
+                       serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
+               } else
+                       serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
+        }
+#endif
+
        if (up->capabilities & UART_NATSEMI) {
                /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
                serial_outp(up, UART_LCR, 0xe0);
@@ -1913,6 +1925,11 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
        unsigned int size = 8 << up->port.regshift;
        int ret = 0;
 
+#ifdef CONFIG_ARCH_OMAP
+       if (is_omap_port((unsigned int)up->port.membase))
+               size = 0x16 << up->port.regshift;
+#endif
+
        switch (up->port.iotype) {
        case UPIO_MEM:
                if (!up->port.mapbase)
diff --git a/drivers/ssi/Kconfig b/drivers/ssi/Kconfig
new file mode 100644 (file)
index 0000000..e84f9d2
--- /dev/null
@@ -0,0 +1,18 @@
+menu "Synchronous Serial Interfaces (SSI)"
+
+config OMAP_UWIRE
+       depends on ARCH_OMAP1
+       tristate "MicroWire support on OMAP"
+       ---help---
+         Say Y here if you want support for the MicroWire interface
+         on an OMAP processor.
+
+config OMAP_TSC2101
+       depends on ARCH_OMAP1 || ARCH_OMAP24XX
+       tristate "TSC2101 codec support for Touchscreen and audio"
+       select OMAP_UWIRE if MACH_OMAP_H3 || MACH_OMAP_H2
+       select GPIOEXPANDER_OMAP if MACH_OMAP_H3
+       ---help---
+         Say Y here if you want support for the TSC2101 codec.  It is
+         needed for touchscreen and audio on OMAP1610 and 1710.
+endmenu
diff --git a/drivers/ssi/Makefile b/drivers/ssi/Makefile
new file mode 100644 (file)
index 0000000..c63cf2b
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the SSI drivers
+#
+
+obj-$(CONFIG_OMAP_UWIRE)        += omap-uwire.o
+obj-$(CONFIG_OMAP_TSC2101)      += omap-tsc2101.o
diff --git a/drivers/ssi/omap-tsc2101.c b/drivers/ssi/omap-tsc2101.c
new file mode 100644 (file)
index 0000000..193542f
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * linux/drivers/ssi/omap-tsc2101.c
+ *
+ * TSC2101 codec interface driver for the OMAP platform
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004/11/07   Nishanth Menon - Modified for common hooks for Audio and Touchscreen
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/hardware/clock.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/hardware/tsc2101.h>
+#include <asm/arch/gpioexpander.h>
+
+#include "omap-tsc2101.h"
+
+#if CONFIG_ARCH_OMAP16XX
+#include <../drivers/ssi/omap-uwire.h>
+#else
+#error "Unsupported configuration"
+#endif
+
+#define SPIO 1
+
+static int count;
+static spinlock_t tsc2101_lock = SPIN_LOCK_UNLOCKED;
+static struct clk  * tsc2101_mclk_ck;
+
+static int omap_tsc2101_configure(void);
+
+/* FIXME: add driver model usage to powerdown the tsc2101 on suspend */
+/* Clock  -Hard coding for the time being */
+#define CLK_SOFT_REQ_REG_BASE  (0xFFFE0800+0x34)
+#define SOFT_COM_MCK0_REQ_MASK (0x1<<6)
+
+int omap_tsc2101_enable(void)
+{
+       int ret = 0;
+
+       spin_lock(&tsc2101_lock);
+       if (count++ == 0) {
+               int ret = 0;
+               /* set the Mux to provide MCLK to TSC2101 */
+               if (machine_is_omap_h3()) {
+                       ret = omap_cfg_reg(V5_1710_MCLK_ON);
+               } else {
+                       if (machine_is_omap_h2()) {
+                               ret = omap_cfg_reg(R10_1610_MCLK_ON);
+                       }
+               }
+
+               /* Get the MCLK */
+               tsc2101_mclk_ck = clk_get(NULL, "mclk");
+               if (NULL == tsc2101_mclk_ck) {
+                       printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
+                       ret = -EPERM;
+                       goto done;
+               }
+               if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
+                       printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
+                       ret = -EPERM;
+                       goto done;
+               }
+               clk_enable(tsc2101_mclk_ck);
+
+               ret = omap_tsc2101_configure();
+
+               /* Lock the module */
+               if (!ret && !try_module_get(THIS_MODULE)) {
+                       printk(KERN_CRIT "Failed to get TSC module\n");
+                       ret = -ESTALE;
+               }
+       }
+
+done:
+       spin_unlock(&tsc2101_lock);
+       return ret;
+}
+
+void omap_tsc2101_disable(void)
+{
+       spin_lock(&tsc2101_lock);
+       if (--count == 0) {
+               int ret = 0;
+               /* Remove the Mux to Stop MCLK to TSC2101 */
+               if (machine_is_omap_h3()) {
+                       ret = omap_cfg_reg(V5_1710_MCLK_OFF);
+               } else {
+                       if (machine_is_omap_h2()) {
+                               ret = omap_cfg_reg(R10_1610_MCLK_OFF);
+                       }
+               }
+
+               /* Release the MCLK */
+               clk_disable(tsc2101_mclk_ck);
+               clk_put(tsc2101_mclk_ck);
+               tsc2101_mclk_ck = NULL;
+
+               module_put(THIS_MODULE);
+       }
+       spin_unlock(&tsc2101_lock);
+}
+
+void omap_tsc2101_write(int page, u8 address, u16 data)
+{
+
+       int ret = 0;
+
+       if (machine_is_omap_h2()) {
+               ret =
+                   omap_uwire_data_transfer(1, 
+                                            (((page) << 11) | (address << 5)),
+                                            16, 0, NULL, 1);
+               if (ret) {
+                       printk(KERN_ERR
+                              "uwire-write returned error for address %x\n",
+                              address);
+                       return;
+               }
+               ret = omap_uwire_data_transfer(1, data, 16, 0, NULL, 0);
+               if (ret) {
+                       printk(KERN_ERR
+                              "uwire-write returned error for address %x\n",
+                              address);
+                       return;
+               }
+       }
+       if (machine_is_omap_h3()) {
+
+               ret =
+                   omap_uwire_data_transfer(0, ((page << 11) | (address << 5)),
+                                            16, 0, NULL, 1);
+               if (ret) {
+                       printk(KERN_ERR
+                              "uwire-write returned error for address %x\n",
+                              address);
+                       return;
+               }
+               ret = omap_uwire_data_transfer(0, data, 16, 0, NULL, 0);
+               if (ret) {
+                       printk(KERN_ERR
+                              "uwire-write returned error for address %x\n",
+                              address);
+                       return;
+               }
+       }
+
+}
+
+void omap_tsc2101_reads(int page, u8 startaddress, u16 * data, int numregs)
+{
+       int cs = 0, i;
+       if (machine_is_omap_h2()) {
+               cs = 1;
+       }
+       if (machine_is_omap_h3()) {
+               cs = 0;
+       }
+       (void)omap_uwire_data_transfer(cs, (0x8000 | (page << 11)
+                                           | (startaddress << 5)),
+                                      16, 0, NULL, 1);
+       for (i = 0; i < (numregs - 1); i++, data++) {
+               omap_uwire_data_transfer(cs, 0, 0, 16, data, 1);
+       }
+       omap_uwire_data_transfer(cs, 0, 0, 16, data, 0);
+}
+
+u16 omap_tsc2101_read(int page, u8 address)
+{
+       u16 ret;
+       omap_tsc2101_reads(page, address, &ret, 1);
+       return ret;
+}
+
+/* FIXME: adapt clock divisors for uwire to current ARM xor clock rate */
+static int omap_tsc2101_configure(void)
+{
+       unsigned long uwire_flags = 0;
+
+#ifdef CONFIG_MACH_OMAP_H3
+       int err = 0;
+       u8 ioExpanderVal = 0;
+
+       if ((err = read_gpio_expa(&ioExpanderVal, 0x24))) {
+               printk(" Error reading from I/O EXPANDER \n");
+               return err;
+       }
+       ioExpanderVal |= 0x8;
+
+       if ((err = write_gpio_expa(ioExpanderVal, 0x24))) {
+               printk(KERN_ERR ": Error writing to I/O EXPANDER \n");
+               return err;
+       }
+#endif
+
+       if (machine_is_omap_h2()) {
+               uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
+               omap_cfg_reg(N15_1610_UWIRE_CS1);
+               omap_uwire_configure_mode(1, uwire_flags);
+       }
+       if (machine_is_omap_h3()) {
+               uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
+               omap_cfg_reg(N14_1610_UWIRE_CS0);
+               omap_uwire_configure_mode(0, uwire_flags);
+       }
+
+       /* Configure MCLK enable */
+       omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);  
+
+       return 0;
+}
+
+EXPORT_SYMBOL(omap_tsc2101_enable);
+EXPORT_SYMBOL(omap_tsc2101_read);
+EXPORT_SYMBOL(omap_tsc2101_reads);
+EXPORT_SYMBOL(omap_tsc2101_write);
+EXPORT_SYMBOL(omap_tsc2101_disable);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION
+    ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ssi/omap-tsc2101.h b/drivers/ssi/omap-tsc2101.h
new file mode 100644 (file)
index 0000000..f6b40b8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * linux/drivers/ssi/omap-tsc2101.h
+ *
+ * TSC2101 codec interface driver for the OMAP platform
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004/11/07   Nishanth Menon - Provided common hooks for Audio and Touchscreen
+ */
+
+#ifndef __OMAP_TSC2101_H
+#define __OMAP_TSC2101_H
+
+extern u16 omap_tsc2101_read(int page, u8 address);
+extern void omap_tsc2101_reads(int page, u8 startaddress, u16 * data,
+                              int numregs);
+extern void omap_tsc2101_write(int page, u8 address, u16 data);
+
+extern void omap_tsc2101_disable(void);
+extern int omap_tsc2101_enable(void);
+
+#endif
diff --git a/drivers/ssi/omap-uwire.c b/drivers/ssi/omap-uwire.c
new file mode 100644 (file)
index 0000000..61b3ca1
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *
+ *     uWire interface driver for the OMAP Platform
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *        source@mvista.com
+ *
+ * Ported to 2.6 uwire interface.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Generalization patches 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 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/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/omap730.h>  /* OMAP730_IO_CONF registers */
+
+#include "omap-uwire.h"
+
+/* uWire Registers: */
+#define UWIRE_BASE    0xFFFB3000
+#define UWIRE_IO_SIZE 0x20
+#define UWIRE_TDR     0x00
+#define UWIRE_RDR     0x00
+#define UWIRE_CSR     0x01
+#define UWIRE_SR1     0x02
+#define UWIRE_SR2     0x03
+#define UWIRE_SR3     0x04
+#define UWIRE_SR4     0x05
+#define UWIRE_SR5     0x06
+
+static unsigned short uwire_flags[4];
+static unsigned long uwire_base = io_p2v(UWIRE_BASE);
+static spinlock_t uwire_lock;
+static unsigned int uwire_idx_shift;
+
+static inline void uwire_write_reg(int idx, u16 val)
+{
+       __raw_writew(val, uwire_base + (idx << uwire_idx_shift));
+}
+
+static inline u16 uwire_read_reg(int idx)
+{
+       return __raw_readw(uwire_base + (idx << uwire_idx_shift));
+}
+
+void omap_uwire_configure_mode(int cs, unsigned long flags)
+{
+       u16 w, val = 0;
+       int shift, reg;
+
+       BUG_ON(cs > 3);
+
+       val = flags & 0x3f;
+       if (flags & UWIRE_CLK_INVERTED)
+               val ^= 0x03;
+       if (cs & 1)
+               shift = 6;
+       else
+               shift = 0;
+       if (cs <= 1)
+               reg = UWIRE_SR1;
+       else
+               reg = UWIRE_SR2;
+       spin_lock(&uwire_lock);
+       w = uwire_read_reg(reg);
+       w &= ~(0x3f << shift);
+       w |= val << shift;
+       uwire_write_reg(reg, w);
+       spin_unlock(&uwire_lock);
+
+       uwire_flags[cs] = flags;
+}
+
+static int wait_uwire_csr_flag(u16 mask, u16 val, int might_not_catch)
+{
+       u16 w;
+       int c = 0;
+       unsigned long max_jiffies = jiffies + HZ;
+
+       for (;;) {
+               w = uwire_read_reg(UWIRE_CSR);
+               if ((w & mask) == val)
+                       break;
+               if (time_after(jiffies, max_jiffies)) {
+                       printk(KERN_ERR "%s: timeout. reg=%#06x mask=%#06x val=%#06x\n",
+                              __FUNCTION__, w, mask, val);
+                       return -1;
+               }
+               c++;
+               if (might_not_catch && c > 64)
+                       break;
+       }
+       return 0;
+}
+
+int omap_uwire_data_transfer(int cs, u16 tx_data, int tx_size, int rx_size,
+                            u16 *rx_buf, int leave_cs_active)
+{
+       u16 ret = -1, w;
+       u16 mask;
+
+       BUG_ON(cs > 3);
+       BUG_ON(rx_size && !rx_buf);
+
+       spin_lock(&uwire_lock);
+
+       if (wait_uwire_csr_flag(1 << 14, 0, 0))
+               goto exit;
+
+       if (uwire_flags[cs] & UWIRE_CLK_INVERTED)
+               uwire_write_reg(UWIRE_SR4, 1);
+       else
+               uwire_write_reg(UWIRE_SR4, 0);
+
+       w = cs << 10;
+       w |= 1 << 12;                           /* CS_CMD : activate CS */
+       uwire_write_reg(UWIRE_CSR, w);
+
+       /* Shift data to 16bit MSb and place it in TX register. */
+       uwire_write_reg(UWIRE_TDR, tx_data << (16 - tx_size));
+
+       if (wait_uwire_csr_flag(1 << 14, 0, 0))
+               goto exit;
+
+       w = rx_size | (tx_size << 5) | (cs << 10);
+       w |= (1 << 12) | (1 << 13);
+       /* Start uWire read/write */
+       uwire_write_reg(UWIRE_CSR, w);
+
+       /* Wait till read/write actually starts.
+        * This is needed at high (>=60MHz) MPU frequencies
+        * REVISIT: But occasionally we won't have time to catch it
+        */
+       if (wait_uwire_csr_flag(1 << 14, 1 << 14, 1))
+               goto exit;
+
+       /* Wait for both transfers to be completed */
+       mask = 1 << 14;                 /* CSRB : reg busy */
+       w = 0;
+       if (rx_size) {
+               mask |= 1 << 15;        /* RDRB : reg busy */
+               w |= 1 << 15;
+       }
+
+       if (wait_uwire_csr_flag(mask, w, 0))
+               goto exit;
+
+       if (rx_size)
+               *rx_buf = uwire_read_reg(UWIRE_RDR);
+
+       if (!leave_cs_active)
+               uwire_write_reg(UWIRE_CSR, cs << 10);
+
+       ret = 0;
+
+exit:
+       spin_unlock(&uwire_lock);
+       return ret;
+}
+
+static int __init omap_uwire_init(void)
+{
+       spin_lock_init(&uwire_lock);
+       if (cpu_is_omap730())
+               uwire_idx_shift = 1;
+       else
+               uwire_idx_shift = 2;
+
+       uwire_write_reg(UWIRE_SR3, 1);
+       if (machine_is_omap_h2()) {
+               /* defaults: W21 SDO, U18 SDI, V19 SCL */
+               omap_cfg_reg(N14_1610_UWIRE_CS0);
+               omap_cfg_reg(N15_1610_UWIRE_CS1);
+       }
+       if (machine_is_omap_osk()) {
+               /* this is the standard expansion connector usage, with
+                * the other chipselect pins for MPUIO2 and MPUIO4.
+                */
+               omap_cfg_reg(N14_1610_UWIRE_CS0);
+               omap_cfg_reg(P15_1610_UWIRE_CS3);
+       }
+       if (machine_is_omap_perseus2()) {
+               /* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
+               int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000;
+               omap_writel(val | 0x00AAA000, OMAP730_IO_CONF_9);
+       }
+       return 0;
+}
+
+static void __exit omap_uwire_exit(void)
+{
+}
+
+subsys_initcall(omap_uwire_init);
+module_exit(omap_uwire_exit);
+
+EXPORT_SYMBOL(omap_uwire_configure_mode);
+EXPORT_SYMBOL(omap_uwire_data_transfer);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/ssi/omap-uwire.h b/drivers/ssi/omap-uwire.h
new file mode 100644 (file)
index 0000000..a0d24bc
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ARCH_OMAP_UWIRE_H
+#define __ARCH_OMAP_UWIRE_H
+
+#define UWIRE_READ_FALLING_EDGE                0x0000
+#define UWIRE_READ_RISING_EDGE         0x0001
+#define UWIRE_WRITE_FALLING_EDGE       0x0000
+#define UWIRE_WRITE_RISING_EDGE                0x0002
+#define UWIRE_CS_ACTIVE_LOW            0x0000
+#define UWIRE_CS_ACTIVE_HIGH           0x0004
+#define UWIRE_FREQ_DIV_2               0x0000
+#define UWIRE_FREQ_DIV_4               0x0008
+#define UWIRE_FREQ_DIV_8               0x0010
+#define UWIRE_CHK_READY                        0x0020
+#define UWIRE_CLK_INVERTED             0x0040
+
+/*
+ * uWire for OMAP declarations
+ */
+extern void omap_uwire_configure_mode(int cs, unsigned long flags);
+
+/* NOTE: Make sure you don't call this from an interrupt handler! */
+extern int omap_uwire_data_transfer(int cs, u16 tx_data, int tx_size,
+                                   int rx_size, u16 *rx_buf,
+                                   int leave_cs_active);
+
+#endif
index ff075a53c8d66787461b634925c317d8e2ea648a..75e15b1ae9ae623004939c003bc0b1d331680fe9 100644 (file)
@@ -157,7 +157,7 @@ config USB_LH7A40X
 
 config USB_GADGET_OMAP
        boolean "OMAP USB Device Controller"
-       depends on ARCH_OMAP
+       depends on ARCH_OMAP1
        select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
        help
           Many Texas Instruments OMAP processors have flexible full
index 387692a3611e7119560b606611e75d1ac881285f..3e372fd6dedf4cf603592cb78ee9b2243b10d563 100644 (file)
@@ -544,9 +544,9 @@ static inline dma_addr_t dma_csac(unsigned lch)
        /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
         * read before the DMA controller finished disabling the channel.
         */
-       csac = omap_readw(OMAP_DMA_CSAC(lch));
+       csac = OMAP_DMA_CSAC_REG(lch);
        if (csac == 0)
-               csac = omap_readw(OMAP_DMA_CSAC(lch));
+               csac = OMAP_DMA_CSAC_REG(lch);
        return csac;
 }
 
@@ -557,9 +557,9 @@ static inline dma_addr_t dma_cdac(unsigned lch)
        /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
         * read before the DMA controller finished disabling the channel.
         */
-       cdac = omap_readw(OMAP_DMA_CDAC(lch));
+       cdac = OMAP_DMA_CDAC_REG(lch);
        if (cdac == 0)
-               cdac = omap_readw(OMAP_DMA_CDAC(lch));
+               cdac = OMAP_DMA_CDAC_REG(lch);
        return cdac;
 }
 
@@ -584,7 +584,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
 }
 
 #define DMA_DEST_LAST(x) (cpu_is_omap15xx() \
-               ? omap_readw(OMAP_DMA_CSAC(x)) /* really: CPC */ \
+               ? OMAP_DMA_CSAC_REG(x) /* really: CPC */ \
                : dma_cdac(x))
 
 static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
@@ -622,17 +622,19 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
                        || (cpu_is_omap15xx() && length < ep->maxpacket)) {
                txdma_ctrl = UDC_TXN_EOT | length;
                omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-                               length, 1, sync_mode);
+                               length, 1, sync_mode, 0, 0);
        } else {
                length = min(length / ep->maxpacket,
                                (unsigned) UDC_TXN_TSC + 1);
                txdma_ctrl = length;
                omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-                               ep->ep.maxpacket >> 1, length, sync_mode);
+                               ep->ep.maxpacket >> 1, length, sync_mode,
+                               0, 0);
                length *= ep->maxpacket;
        }
        omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
-               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+               0, 0);
 
        omap_start_dma(ep->lch);
        ep->dma_counter = dma_csac(ep->lch);
@@ -677,9 +679,11 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
        req->dma_bytes = packets * ep->ep.maxpacket;
        omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
                        ep->ep.maxpacket >> 1, packets,
-                       OMAP_DMA_SYNC_ELEMENT);
+                       OMAP_DMA_SYNC_ELEMENT,
+                       0, 0);
        omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
-               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+               OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+               0, 0);
        ep->dma_counter = DMA_DEST_LAST(ep->lch);
 
        UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
@@ -822,7 +826,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
                        omap_set_dma_dest_params(ep->lch,
                                OMAP_DMA_PORT_TIPB,
                                OMAP_DMA_AMODE_CONSTANT,
-                               (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+                               (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+                               0, 0);
                }
        } else {
                status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
@@ -833,7 +838,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
                        omap_set_dma_src_params(ep->lch,
                                OMAP_DMA_PORT_TIPB,
                                OMAP_DMA_AMODE_CONSTANT,
-                               (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+                               (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+                               0, 0);
                        /* EMIFF */
                        omap_set_dma_dest_burst_mode(ep->lch,
                                                OMAP_DMA_DATA_BURST_4);
@@ -848,7 +854,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 
                /* channel type P: hw synch (fifo) */
                if (!cpu_is_omap15xx())
-                       omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+                       OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
        }
 
 just_restart:
@@ -895,7 +901,7 @@ static void dma_channel_release(struct omap_ep *ep)
        else
                req = NULL;
 
-       active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0;
+       active = ((1 << 7) & OMAP_DMA_CCR_REG(ep->lch)) != 0;
 
        DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
                        active ? "active" : "idle",
index e46cc540cf4d3153fb49d9b942dfdf5652dc4f76..167e95ecc63ef4a1ff41ea37188b4bc0c5cddc4d 100644 (file)
@@ -70,11 +70,11 @@ static struct clk *usb_host_ck;
 static void omap_ohci_clock_power(int on)
 {
        if (on) {
-               clk_enable(usb_host_ck);
+               clk_use(usb_host_ck);
                /* guesstimate for T5 == 1x 32K clock + APLL lock time */
                udelay(100);
        } else {
-               clk_disable(usb_host_ck);
+               clk_unuse(usb_host_ck);
        }
 }
 
@@ -103,6 +103,7 @@ static int omap_ohci_transceiver_power(int on)
        return 0;
 }
 
+#ifdef CONFIG_ARCH_OMAP15XX
 /*
  * OMAP-1510 specific Local Bus clock on/off
  */
@@ -152,6 +153,10 @@ static int omap_1510_local_bus_init(void)
 
        return 0;
 }
+#else
+#define omap_1510_local_bus_power(x)   {}
+#define omap_1510_local_bus_init()     {}
+#endif
 
 #ifdef CONFIG_USB_OTG
 
@@ -494,6 +499,7 @@ static int ohci_omap_resume(struct device *dev)
 /*
  * Driver definition to register with the OMAP bus
  */
+MODULE_ALIAS("ohci");
 static struct device_driver ohci_hcd_omap_driver = {
        .name           = "ohci",
        .owner          = THIS_MODULE,
index 25b6ca6ad081a17d4c69ffe11cd388595a530291..8a488fd8b35499180f03216096294f4a4d91228c 100644 (file)
@@ -1436,6 +1436,8 @@ config FB_S3C2410_DEBUG
          Turn on debugging messages. Note that you can set/unset at run time
          through sysfs
 
+source "drivers/video/omap/Kconfig"
+
 config FB_VIRTUAL
        tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
        depends on FB
index aa434e725c0d844af830a0f273339d26c19d0d1b..4528b65b42ee8b46f25054668e3eef5754b49da5 100644 (file)
@@ -99,6 +99,7 @@ obj-$(CONFIG_FB_S3C2410)        += s3c2410fb.o
 obj-$(CONFIG_FB_VESA)             += vesafb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
 obj-$(CONFIG_FB_OF)               += offb.o
+obj-$(CONFIG_FB_OMAP)            += omap/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
new file mode 100644 (file)
index 0000000..3bf5df7
--- /dev/null
@@ -0,0 +1,39 @@
+config FB_OMAP
+       tristate "OMAP frame buffer support (EXPERIMENTAL)"
+        depends on FB
+        help
+          Frame buffer driver for OMAP based boards.
+
+config FB_OMAP_LCDC_INTERNAL
+       bool "Internal LCD controller support"
+       depends on FB_OMAP
+       help
+         Say Y here, if you want to have support for the internal OMAP
+         LCD controller. If unsure, say Y.
+
+config FB_OMAP_LCDC_EXTERNAL
+       bool "External LCD controller support"
+       depends on FB_OMAP
+       help
+         Say Y here, if you want to have support for boards with an
+         external LCD controller connected to the SoSSI/RFBI interface. 
+
+config FB_OMAP_MANUAL_UPDATE
+       bool "Default to manual update mode"
+       depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
+       help
+         Say Y here, if your user-space applications are capable of
+         notifying the frame buffer driver when a change has occured in
+          the frame buffer content and thus a reload of the image data to
+         the external frame buffer is required. If unsure, say N.
+
+config FB_OMAP_DMA_TUNE
+        bool "Set DMA SDRAM access priority high"
+        depends on FB_OMAP && ARCH_OMAP1
+        help
+          On systems in which video memory is in system memory
+          (SDRAM) this will speed up graphics DMA operations.
+          If you have such a system and want to use rotation
+          answer yes. Answer no if you have a dedicated video
+          memory, or don't use any of the accelerated features.
+
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
new file mode 100644 (file)
index 0000000..391bf3f
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# Makefile for the new OMAP framebuffer device driver
+#
+
+obj-$(CONFIG_FB_OMAP) += omapfb.o
+
+objs-yy := omapfb_main.o
+
+objs-y$(CONFIG_ARCH_OMAP2) += dispc.o
+
+objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_INTERNAL) += lcdc.o
+
+objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
+objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
+
+objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
+objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
+objs-y$(CONFIG_MACH_OMAP_H2) += lcd_h2.o
+objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
+objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
+objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
+objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
+objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o
+
+omapfb-objs := $(objs-yy)
+
diff --git a/drivers/video/omap/debug.h b/drivers/video/omap/debug.h
new file mode 100644 (file)
index 0000000..835f28b
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * File: drivers/video/omap_new/debug.c
+ *
+ * Debug support for the omapfb driver
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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.
+ */
+
+#ifndef __OMAPFB_DEBUG_H
+#define __OMAPFB_DEBUG_H
+
+#include <asm/io.h>
+
+#ifdef OMAPFB_DBG
+
+#define DBGPRINT(level, fmt, ...) if (level <= OMAPFB_DBG) do { \
+                                       printk(KERN_DEBUG "%s: "fmt, \
+                                               __FUNCTION__, ## __VA_ARGS__); \
+                                 } while (0)
+#define DBGENTER(level) DBGPRINT(level, "Enter\n")
+#define DBGLEAVE(level)        DBGPRINT(level, "Leave\n")
+
+static inline void dump_dma_regs(int lch)
+{
+#ifdef CONFIG_ARCH_OMAP1
+#define _R(x) __REG16(OMAP_DMA_##x(lch))
+
+       DBGPRINT(4, "\nCSDP  :%#06x CCR      :%#06x CSSA_U  :%#06x "
+                   "\nCDSA_L:%#06x CDSA_U   :%#06x CEN     :%#06x "
+                   "\nCFN   :%#06x CSFI     :%#06x CSEI    :%#06x "
+                   "\nCSAC  :%#06x CICR     :%#06x CSR     :%04x "
+                   "\nCSSA_L:%#06x CDAC     :%#06x CDEI    :%#06x "
+                   "\nCDFI  :%#06x COLOR_L  :%#06x COLOR_U :%#06x "
+                   "\nCCR2  :%#06x CLNK_CTRL:%#06x LCH_CTRL:%#06x\n",
+                   _R(CSDP), _R(CCR), _R(CSSA_U),
+                   _R(CDSA_L), _R(CDSA_U), _R(CEN),
+                   _R(CFN), _R(CSFI), _R(CSEI),
+                   _R(CSAC), _R(CICR), 0, /* _R(CSR), */
+                   _R(CSSA_L), _R(CDAC), _R(CDEI),
+                   _R(CDFI), _R(COLOR_L), _R(COLOR_U),
+                   _R(CCR2), _R(CLNK_CTRL), _R(LCH_CTRL));
+#undef _R
+#endif
+}
+
+#define DUMP_DMA_REGS(lch) dump_dma_regs(lch)
+
+#else  /* OMAPFB_DBG */
+
+#define DBGPRINT(level, format, ...)
+#define DBGENTER(level)
+#define DBGLEAVE(level)
+#define DUMP_DMA_REGS(lch)
+
+#endif /* OMAPFB_DBG */
+
+#endif /* __OMAPFB_DEBUG_H */
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
new file mode 100644 (file)
index 0000000..eb85628
--- /dev/null
@@ -0,0 +1,838 @@
+/*
+ * File: drivers/video/omap/omap2/dispc.c
+ *
+ * OMAP2 display controller support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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/kernel.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/omapfb.h>
+
+#include <asm/hardware/clock.h>
+
+#include "dispc.h"
+
+/* #define OMAPFB_DBG  2 */
+
+#include "debug.h"
+
+#define MODULE_NAME                    "omapfb-dispc"
+
+#define DISPC_BASE                     0x48050400
+
+/* DISPC common */
+#define DISPC_REVISION                 0x0000
+#define DISPC_SYSCONFIG                        0x0010
+#define DISPC_SYSSTATUS                        0x0014
+#define DISPC_IRQSTATUS                        0x0018
+#define DISPC_IRQENABLE                        0x001C
+#define DISPC_CONTROL                  0x0040
+#define DISPC_CONFIG                   0x0044
+#define DISPC_CAPABLE                  0x0048
+#define DISPC_DEFAULT_COLOR0           0x004C
+#define DISPC_DEFAULT_COLOR1           0x0050
+#define DISPC_TRANS_COLOR0             0x0054
+#define DISPC_TRANS_COLOR1             0x0058
+#define DISPC_LINE_STATUS              0x005C
+#define DISPC_LINE_NUMBER              0x0060
+#define DISPC_TIMING_H                 0x0064
+#define DISPC_TIMING_V                 0x0068
+#define DISPC_POL_FREQ                 0x006C
+#define DISPC_DIVISOR                  0x0070
+#define DISPC_SIZE_DIG                 0x0078
+#define DISPC_SIZE_LCD                 0x007C
+
+#define DISPC_DATA_CYCLE1              0x01D4
+#define DISPC_DATA_CYCLE2              0x01D8
+#define DISPC_DATA_CYCLE3              0x01DC
+
+/* DISPC GFX plane */
+#define DISPC_GFX_BA0                  0x0080
+#define DISPC_GFX_BA1                  0x0084
+#define DISPC_GFX_POSITION             0x0088
+#define DISPC_GFX_SIZE                 0x008C
+#define DISPC_GFX_ATTRIBUTES           0x00A0
+#define DISPC_GFX_FIFO_THRESHOLD       0x00A4
+#define DISPC_GFX_FIFO_SIZE_STATUS     0x00A8
+#define DISPC_GFX_ROW_INC              0x00AC
+#define DISPC_GFX_PIXEL_INC            0x00B0
+#define DISPC_GFX_WINDOW_SKIP          0x00B4
+#define DISPC_GFX_TABLE_BA             0x00B8
+
+/* DISPC Video plane 1/2 */
+#define DISPC_VID1_BASE                        0x00BC
+#define DISPC_VID2_BASE                        0x014C
+
+/* Offsets into DISPC_VID1/2_BASE */
+#define DISPC_VID_BA0                  0x0000
+#define DISPC_VID_BA1                  0x0004
+#define DISPC_VID_POSITION             0x0008
+#define DISPC_VID_SIZE                 0x000C
+#define DISPC_VID_ATTRIBUTES           0x0010
+#define DISPC_VID_FIFO_THRESHOLD       0x0014
+#define DISPC_VID_FIFO_SIZE_STATUS     0x0018
+#define DISPC_VID_ROW_INC              0x001C
+#define DISPC_VID_PIXEL_INC            0x0020
+#define DISPC_VID_FIR                  0x0024
+#define DISPC_VID_PICTURE_SIZE         0x0028
+#define DISPC_VID_ACCU0                        0x002C
+#define DISPC_VID_ACCU1                        0x0030
+
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_H0          0x0034
+/* 8 elements in 8 byte increments */
+#define DISPC_VID_FIR_COEF_HV0         0x0038
+/* 5 elements in 4 byte increments */
+#define DISPC_VID_CONV_COEF0           0x0074
+
+#define DISPC_IRQ_FRAMEMASK            0x0001
+#define DISPC_IRQ_VSYNC                        0x0002
+#define DISPC_IRQ_EVSYNC_EVEN          0x0004
+#define DISPC_IRQ_EVSYNC_ODD           0x0008
+#define DISPC_IRQ_ACBIAS_COUNT_STAT    0x0010
+#define DISPC_IRQ_PROG_LINE_NUM                0x0020
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW   0x0040
+#define DISPC_IRQ_GFX_END_WIN          0x0080
+#define DISPC_IRQ_PAL_GAMMA_MASK       0x0100
+#define DISPC_IRQ_OCP_ERR              0x0200
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW  0x0400
+#define DISPC_IRQ_VID1_END_WIN         0x0800
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW  0x1000
+#define DISPC_IRQ_VID2_END_WIN         0x2000
+#define DISPC_IRQ_SYNC_LOST            0x4000
+
+#define DISPC_IRQ_MASK_ALL             0x7fff
+
+#define DISPC_IRQ_MASK_ERROR           (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+                                            DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+                                            DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+                                            DISPC_IRQ_SYNC_LOST)
+
+#define MAX_PALETTE_SIZE               256 * 16
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+#define FLD_MASK(pos, len)     (((1 << len) - 1) << pos)
+
+#define MOD_REG_FLD(reg, mask, val) \
+       dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
+
+static struct {
+       u32             base;
+       void            *vram_virt;
+       dma_addr_t      vram_phys;
+       int             vram_size;
+
+       int             ext_mode;
+
+       unsigned long   enabled_irqs;
+       void            (*irq_callback)(void *);
+       void            *irq_callback_data;
+       struct completion       frame_done;
+
+       struct clk      *dss_ick, *dss1_fck;
+       struct clk      *dss_54m_fck;
+
+       int             active_plane_mask;
+
+       enum omapfb_update_mode update_mode;
+       struct omapfb_device    *fbdev;
+} dispc;
+
+static void inline dispc_write_reg(int idx, u32 val)
+{
+       __raw_writel(val, dispc.base + idx);
+}
+
+static u32 inline dispc_read_reg(int idx)
+{
+       u32 l = __raw_readl(dispc.base + idx);
+       return l;
+}
+
+/* Select RFBI or bypass mode */
+static void enable_rfbi_mode(int enable)
+{
+       u32 l;
+
+       l = dispc_read_reg(DISPC_CONTROL);
+       /* Enable RFBI, GPIO0/1 */
+       l &= ~((1 << 11) | (1 << 15) | (1 << 16));
+       l |= enable ? (1 << 11) : 0;
+       /* RFBI En: GPIO0/1=10  RFBI Dis: GPIO0/1=11 */
+       l |= 1 << 15;
+       l |= enable ? 0 : (1 << 16);
+       dispc_write_reg(DISPC_CONTROL, l);
+}
+
+static void set_lcd_data_lines(int data_lines)
+{
+       u32 l;
+       int code = 0;
+
+       switch (data_lines) {
+       case 12:
+               code = 0;
+               break;
+       case 16:
+               code = 1;
+               break;
+       case 18:
+               code = 2;
+               break;
+       case 24:
+               code = 3;
+               break;
+       default:
+               BUG();
+       }
+
+       l = dispc_read_reg(DISPC_CONTROL);
+       l &= ~(0x03 << 8);
+       l |= code << 8;
+       dispc_write_reg(DISPC_CONTROL, l);
+}
+
+static void set_load_mode(int mode)
+{
+       BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
+                       DISPC_LOAD_CLUT_ONCE_FRAME));
+       MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
+}
+
+void omap_dispc_set_lcd_size(int x, int y)
+{
+       BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+       MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+                       ((y - 1) << 16) | (x - 1));
+}
+EXPORT_SYMBOL(omap_dispc_set_lcd_size);
+
+void omap_dispc_set_digit_size(int x, int y)
+{
+       BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+       MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+                       ((y - 1) << 16) | (x - 1));
+}
+EXPORT_SYMBOL(omap_dispc_set_digit_size);
+
+static void setup_plane_fifo(int plane)
+{
+       const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+                               DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
+                               DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
+       const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+                               DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
+                               DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
+
+       u32 l;
+
+       BUG_ON(plane > 2);
+
+       l = dispc_read_reg(fsz_reg[plane]);
+       l &= FLD_MASK(0, 9);
+       /* HIGH=3/4 LOW=1/4 */
+       MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9),
+                       ((l * 3 / 4) << 16) | (l / 4));
+}
+
+void omap_dispc_enable_lcd_out(int enable)
+{
+       MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
+
+void omap_dispc_enable_digit_out(int enable)
+{
+       MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
+}
+EXPORT_SYMBOL(omap_dispc_enable_digit_out);
+
+static int omap_dispc_setup_plane(int plane, int channel_out,
+                                 unsigned long offset, int screen_width,
+                                 int pos_x, int pos_y, int width, int height,
+                                 int color_mode)
+{
+       const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+                               DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+                               DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+       const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
+                               DISPC_VID2_BASE + DISPC_VID_BA0 };
+       const u32 ps_reg[] = { DISPC_GFX_POSITION,
+                               DISPC_VID1_BASE + DISPC_VID_POSITION,
+                               DISPC_VID2_BASE + DISPC_VID_POSITION };
+       const u32 sz_reg[] = { DISPC_GFX_SIZE, DISPC_VID1_BASE + DISPC_VID_SIZE,
+                               DISPC_VID2_BASE + DISPC_VID_SIZE };
+       const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
+                               DISPC_VID1_BASE + DISPC_VID_ROW_INC,
+                               DISPC_VID2_BASE + DISPC_VID_ROW_INC };
+       int chout_shift, burst_shift;
+       int chout_val;
+       int color_code;
+       int bpp;
+       u32 l;
+
+       DBGENTER(1);
+
+       switch (plane) {
+       case OMAPFB_PLANE_GFX:
+               burst_shift = 6;
+               chout_shift = 8;
+               break;
+       case OMAPFB_PLANE_VID1:
+       case OMAPFB_PLANE_VID2:
+               burst_shift = 14;
+               chout_shift = 16;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (channel_out) {
+       case OMAPFB_CHANNEL_OUT_LCD:
+               chout_val = 0;
+               break;
+       case OMAPFB_CHANNEL_OUT_DIGIT:
+               chout_val = 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (color_mode) {
+       case OMAPFB_COLOR_RGB565:
+               color_code = DISPC_RGB_16_BPP;
+               bpp = 16;
+               break;
+       case OMAPFB_COLOR_YUV422:
+               if (plane != 0)
+                       return -EINVAL;
+               color_code = DISPC_UYVY_422;
+               bpp = 16;
+               break;
+       case OMAPFB_COLOR_YUV420:
+               if (plane != 0)
+                       return -EINVAL;
+               color_code = DISPC_YUV2_422;
+               bpp = 12;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       l = dispc_read_reg(at_reg[plane]);
+
+       l &= ~(0x0f << 1);
+       l |= color_code << 1;
+
+       l &= ~(0x03 << burst_shift);
+       l |= DISPC_BURST_8x32 << burst_shift;
+
+       l &= ~(1 << chout_shift);
+       l |= chout_val << chout_shift;
+
+       dispc_write_reg(at_reg[plane], l);
+
+
+       dispc_write_reg(ba_reg[plane],
+                      dispc.vram_phys + PAGE_ALIGN(MAX_PALETTE_SIZE) + offset);
+
+       MOD_REG_FLD(ps_reg[plane],
+                   FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
+
+       MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
+                       ((height - 1) << 16) | (width - 1));
+
+       dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
+
+       return 0;
+}
+
+static int omap_dispc_enable_plane(int plane, int enable)
+{
+       const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
+                               DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
+                               DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
+       DBGENTER(1);
+
+       if ((unsigned int)plane > 2)
+               return -EINVAL;
+       MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
+
+       return 0;
+}
+
+static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
+{
+       u32 df_reg, tr_reg;
+       int shift, val;
+
+       switch (ck->channel_out) {
+       case OMAPFB_CHANNEL_OUT_LCD:
+               df_reg = DISPC_DEFAULT_COLOR0;
+               tr_reg = DISPC_TRANS_COLOR0;
+               shift = 10;
+               break;
+       case OMAPFB_CHANNEL_OUT_DIGIT:
+               df_reg = DISPC_DEFAULT_COLOR1;
+               tr_reg = DISPC_TRANS_COLOR1;
+               shift = 12;
+               break;
+       default:
+               return -EINVAL;
+       }
+       switch (ck->key_type) {
+       case OMAPFB_COLOR_KEY_DISABLED:
+               val = 0;
+               break;
+       case OMAPFB_COLOR_KEY_GFX_DST:
+               val = 1;
+               break;
+       case OMAPFB_COLOR_KEY_VID_SRC:
+               val = 3;
+               break;
+       default:
+               return -EINVAL;
+       }
+       MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
+
+       if (val != 0)
+               dispc_write_reg(tr_reg, ck->trans_key);
+       dispc_write_reg(df_reg, ck->background);
+
+       return 0;
+}
+
+static void load_palette(void)
+{
+}
+
+static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
+{
+       int r = 0;
+
+       DBGENTER(1);
+
+       if (mode != dispc.update_mode) {
+               switch (mode) {
+               case OMAPFB_AUTO_UPDATE:
+                       omap_dispc_enable_lcd_out(1);
+                       dispc.update_mode = mode;
+                       break;
+               case OMAPFB_UPDATE_DISABLED:
+                       init_completion(&dispc.frame_done);
+                       omap_dispc_enable_lcd_out(0);
+                       if (!wait_for_completion_timeout(&dispc.frame_done,
+                                       msecs_to_jiffies(500))) {
+                               pr_err("timeout waiting for FRAME DONE\n");
+                       }
+                       dispc.update_mode = mode;
+                       break;
+               default:
+                       r = -EINVAL;
+               }
+       }
+
+       DBGLEAVE(1);
+
+       return r;
+}
+
+static enum omapfb_update_mode omap_dispc_get_update_mode(void)
+{
+       return dispc.update_mode;
+}
+
+static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
+{
+       unsigned long fck, lck;
+
+       *lck_div = 1;
+       pck = max(1, pck);
+       fck = clk_get_rate(dispc.dss1_fck);
+       lck = fck;
+       *pck_div = lck / pck;
+       if (is_tft)
+               *pck_div = max(2, *pck_div);
+       else
+               *pck_div = max(3, *pck_div);
+       if (*pck_div > 255) {
+               *pck_div = 255;
+               lck = pck * *pck_div;
+               *lck_div = fck / lck;
+               BUG_ON(*lck_div < 1);
+               if (*lck_div > 255) {
+                       *lck_div = 255;
+                       printk(KERN_WARNING
+                               MODULE_NAME ": pixclock %d kHz too low.\n",
+                                pck / 1000);
+               }
+       }
+}
+
+static void set_lcd_timings(void)
+{
+       u32 l;
+       int lck_div, pck_div;
+       struct lcd_panel *panel = dispc.fbdev->panel;
+       int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+       unsigned long fck;
+
+       DBGENTER(1);
+
+       /* TFT dither, TFT/STN */
+       l = (1 << 7) | (1 << 3);
+       MOD_REG_FLD(DISPC_CONTROL, l, is_tft ? l : 0);
+
+       l = dispc_read_reg(DISPC_TIMING_H);
+       l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+       l |= ( max(1, (min(64,  panel->hsw))) - 1 ) << 0;
+       l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
+       l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
+       dispc_write_reg(DISPC_TIMING_H, l);
+
+       l = dispc_read_reg(DISPC_TIMING_V);
+       l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
+       l |= ( max(1, (min(64,  panel->vsw))) - 1 ) << 0;
+       l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
+       l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
+       dispc_write_reg(DISPC_TIMING_V, l);
+
+       l = dispc_read_reg(DISPC_POL_FREQ);
+       l &= ~FLD_MASK(12, 6);
+       l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
+       l |= panel->acb & 0xff;
+       dispc_write_reg(DISPC_POL_FREQ, l);
+
+       calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
+
+       l = dispc_read_reg(DISPC_DIVISOR);
+       l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
+       l |= (lck_div << 16) | (pck_div << 0);
+       dispc_write_reg(DISPC_DIVISOR, l);
+
+       /* update panel info with the exact clock */
+       fck = clk_get_rate(dispc.dss1_fck);
+       panel->pixel_clock = fck / lck_div / pck_div / 1000;
+}
+
+int omap_dispc_request_irq(void (*callback)(void *data), void *data)
+{
+       int r = 0;
+
+       BUG_ON(callback == NULL);
+
+       if (dispc.irq_callback)
+               r = -EBUSY;
+       else {
+               dispc.irq_callback = callback;
+               dispc.irq_callback_data = data;
+       }
+
+       return r;
+}
+EXPORT_SYMBOL(omap_dispc_request_irq);
+
+void omap_dispc_enable_irqs(int irq_mask)
+{
+       dispc.enabled_irqs = irq_mask;
+       irq_mask |= DISPC_IRQ_MASK_ERROR;
+       MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+}
+EXPORT_SYMBOL(omap_dispc_enable_irqs);
+
+void omap_dispc_disable_irqs(int irq_mask)
+{
+       dispc.enabled_irqs &= ~irq_mask;
+       irq_mask &= ~DISPC_IRQ_MASK_ERROR;
+       MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
+}
+EXPORT_SYMBOL(omap_dispc_disable_irqs);
+
+void omap_dispc_free_irq(void)
+{
+       omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL);
+       dispc.irq_callback = NULL;
+       dispc.irq_callback_data = NULL;
+}
+EXPORT_SYMBOL(omap_dispc_free_irq);
+
+static irqreturn_t omap_dispc_irq_handler(int irq, void *dev, struct pt_regs *regs)
+{
+       u32 stat = dispc_read_reg(DISPC_IRQSTATUS);
+       static int jabber;
+
+       DBGENTER(2);
+
+       if (stat & DISPC_IRQ_FRAMEMASK)
+               complete(&dispc.frame_done);
+
+       if (stat & DISPC_IRQ_MASK_ERROR) {
+               if (jabber++ < 5) {
+                       pr_err("irq error status %04x\n", stat);
+               } else {
+                       pr_err("disable irq\n");
+                       dispc_write_reg(DISPC_IRQENABLE, 0);
+               }
+       }
+
+       if ((stat & dispc.enabled_irqs) && dispc.irq_callback)
+               dispc.irq_callback(dispc.irq_callback_data);
+
+       dispc_write_reg(DISPC_IRQSTATUS, stat);
+
+       return IRQ_HANDLED;
+}
+
+static int get_dss_clocks(void)
+{
+       if (IS_ERR((dispc.dss_ick = clk_get(dispc.fbdev->dev, "dss_ick")))) {
+               pr_err("can't get dss_ick");
+               return PTR_ERR(dispc.dss_ick);
+       }
+
+       if (IS_ERR((dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck")))) {
+               pr_err("can't get dss1_fck");
+               clk_put(dispc.dss_ick);
+               return PTR_ERR(dispc.dss1_fck);
+       }
+
+       if (IS_ERR((dispc.dss_54m_fck =
+                               clk_get(dispc.fbdev->dev, "dss_54m_fck")))) {
+               pr_err("can't get dss_54m_fck");
+               clk_put(dispc.dss_ick);
+               clk_put(dispc.dss1_fck);
+               return PTR_ERR(dispc.dss_54m_fck);
+       }
+
+       return 0;
+}
+
+static void put_dss_clocks(void)
+{
+       clk_put(dispc.dss_54m_fck);
+       clk_put(dispc.dss1_fck);
+       clk_put(dispc.dss_ick);
+}
+
+static void enable_lcd_clocks(int enable)
+{
+       if (enable) {
+               clk_use(dispc.dss_ick);
+               clk_use(dispc.dss1_fck);
+       } else {
+               clk_unuse(dispc.dss1_fck);
+               clk_unuse(dispc.dss_ick);
+       }
+}
+
+static void enable_digit_clocks(int enable)
+{
+       if (enable)
+               clk_use(dispc.dss_54m_fck);
+       else
+               clk_unuse(dispc.dss_54m_fck);
+}
+
+static void omap_dispc_suspend(void)
+{
+       DBGENTER(1);
+
+       if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+               init_completion(&dispc.frame_done);
+               omap_dispc_enable_lcd_out(0);
+               if (!wait_for_completion_timeout(&dispc.frame_done,
+                               msecs_to_jiffies(500))) {
+                       pr_err("timeout waiting for FRAME DONE\n");
+               }
+               enable_lcd_clocks(0);
+       }
+
+       DBGLEAVE(1);
+}
+
+static void omap_dispc_resume(void)
+{
+       DBGENTER(1);
+
+       if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
+               enable_lcd_clocks(1);
+               set_lcd_timings();
+               load_palette();
+               omap_dispc_enable_lcd_out(1);
+       }
+
+       DBGLEAVE(1);
+}
+
+/* Called when used in bypass mode */
+static int alloc_vram(int req_size)
+{
+       int frame_size;
+       struct lcd_panel *panel = dispc.fbdev->panel;
+
+       frame_size = PAGE_ALIGN(panel->x_res * panel->bpp / 8 * panel->y_res);
+       if (req_size > frame_size)
+               frame_size = req_size;
+       dispc.vram_size = PAGE_ALIGN(MAX_PALETTE_SIZE) + frame_size;
+       dispc.vram_virt = dma_alloc_writecombine(dispc.fbdev->dev,
+                       dispc.vram_size, &dispc.vram_phys, GFP_KERNEL);
+
+       if (dispc.vram_virt == 0) {
+               pr_err("unable to allocate fb DMA memory\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void free_vram(void)
+{
+       dma_free_writecombine(dispc.fbdev->dev, dispc.vram_size,
+                             dispc.vram_virt, dispc.vram_phys);
+}
+
+static void omap_dispc_get_vram_layout(unsigned long *size, void **virt,
+                                       dma_addr_t *phys)
+{
+       *size = dispc.vram_size - PAGE_ALIGN(MAX_PALETTE_SIZE);
+       *virt = (u8 *)dispc.vram_virt + PAGE_ALIGN(MAX_PALETTE_SIZE);
+       *phys = dispc.vram_phys + PAGE_ALIGN(MAX_PALETTE_SIZE);
+}
+
+static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
+                          int req_vram_size)
+{
+       int r;
+       u32 l;
+       struct lcd_panel *panel = fbdev->panel;
+       int tmo = 10000;
+
+       DBGENTER(1);
+
+       memset(&dispc, 0, sizeof(dispc));
+
+       dispc.base = io_p2v(DISPC_BASE);
+       dispc.fbdev = fbdev;
+       dispc.ext_mode = ext_mode;
+
+       if ((r = get_dss_clocks()) < 0)
+               goto fail0;
+
+       enable_lcd_clocks(1);
+       /* Reset monitoring works only w/ the 54M clk */
+       enable_digit_clocks(1);
+
+       l = dispc_read_reg(DISPC_REVISION);
+       pr_info(MODULE_NAME ": version %d.%d\n", l >> 4 & 0x0f, l & 0x0f);
+
+       /* Soft reset */
+       MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
+
+       while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
+               if (!--tmo) {
+                       pr_err("soft reset failed\n");
+                       r = -ENODEV;
+                       enable_digit_clocks(0);
+                       goto fail1;
+               }
+       }
+
+       enable_digit_clocks(0);
+
+       if (!ext_mode && (r = alloc_vram(req_vram_size)) < 0)
+               goto fail1;
+
+       /* Set logic clock to the fck for now */
+       MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1);
+
+       setup_plane_fifo(0);
+       setup_plane_fifo(1);
+       setup_plane_fifo(2);
+
+       l = dispc_read_reg(DISPC_IRQSTATUS);
+       dispc_write_reg(l, DISPC_IRQSTATUS);
+
+       /* Enable those that we handle always */
+       omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
+
+       if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
+                          0, MODULE_NAME, NULL)) < 0) {
+               pr_err("can't get DSS IRQ\n");
+               goto fail2;
+       }
+
+       set_lcd_data_lines(panel->data_lines);
+       set_load_mode(DISPC_LOAD_FRAME_ONLY);
+
+       if (!ext_mode) {
+               omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
+               set_lcd_timings();
+       }
+       enable_rfbi_mode(ext_mode);
+
+       DBGLEAVE(1);
+       return 0;
+fail2:
+       if (ext_mode)
+               free_vram();
+fail1:
+       enable_lcd_clocks(0);
+       put_dss_clocks();
+fail0:
+       DBGLEAVE(1);
+        return r;
+}
+
+static void omap_dispc_cleanup(void)
+{
+       free_irq(INT_24XX_DSS_IRQ, NULL);
+       enable_lcd_clocks(0);
+       put_dss_clocks();
+       if (dispc.ext_mode)
+               free_vram();
+}
+
+static unsigned long omap_dispc_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_ctrl omap2_int_ctrl = {
+       .name                   = "internal",
+       .init                   = omap_dispc_init,
+       .cleanup                = omap_dispc_cleanup,
+       .get_vram_layout        = omap_dispc_get_vram_layout,
+       .get_caps               = omap_dispc_get_caps,
+       .set_update_mode        = omap_dispc_set_update_mode,
+       .get_update_mode        = omap_dispc_get_update_mode,
+       .update_window          = NULL,
+       .suspend                = omap_dispc_suspend,
+       .resume                 = omap_dispc_resume,
+       .setup_plane            = omap_dispc_setup_plane,
+       .enable_plane           = omap_dispc_enable_plane,
+       .set_color_key          = omap_dispc_set_color_key,
+};
+
+MODULE_DESCRIPTION("TI OMAP LCDC controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
new file mode 100644 (file)
index 0000000..eb1512b
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _DISPC_H
+#define _DISPC_H
+
+#include <linux/interrupt.h>
+
+#define DISPC_PLANE_GFX                        0
+#define DISPC_PLANE_VID1               1
+#define DISPC_PLANE_VID2               2
+
+#define DISPC_RGB_1_BPP                        0x00
+#define DISPC_RGB_2_BPP                        0x01
+#define DISPC_RGB_4_BPP                        0x02
+#define DISPC_RGB_8_BPP                        0x03
+#define DISPC_RGB_12_BPP               0x04
+#define DISPC_RGB_16_BPP               0x06
+#define DISPC_RGB_24_BPP               0x08
+#define DISPC_RGB_24_BPP_UNPACK_32     0x09
+#define DISPC_YUV2_422                 0x0a
+#define DISPC_UYVY_422                 0x0b
+
+#define DISPC_BURST_4x32               0
+#define DISPC_BURST_8x32               1
+#define DISPC_BURST_16x32              2
+
+#define DISPC_LOAD_CLUT_AND_FRAME      0x00
+#define DISPC_LOAD_CLUT_ONLY           0x01
+#define DISPC_LOAD_FRAME_ONLY          0x02
+#define DISPC_LOAD_CLUT_ONCE_FRAME     0x03
+
+#define DISPC_TFT_DATA_LINES_12                0
+#define DISPC_TFT_DATA_LINES_16                1
+#define DISPC_TFT_DATA_LINES_18                2
+#define DISPC_TFT_DATA_LINES_24                3
+
+extern void omap_dispc_set_lcd_size(int width, int height);
+
+extern void omap_dispc_enable_lcd_out(int enable);
+extern void omap_dispc_enable_digit_out(int enable);
+
+extern int  omap_dispc_request_irq(void (*callback)(void *data), void *data);
+extern void omap_dispc_free_irq(void);
+
+#endif
diff --git a/drivers/video/omap/lcd_h2.c b/drivers/video/omap/lcd_h2.c
new file mode 100644 (file)
index 0000000..1021739
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * File: drivers/video/omap/lcd-h2.c
+ *
+ * LCD panel support for the TI OMAP H2 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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/module.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+#include "../drivers/ssi/omap-uwire.h"
+
+#define MODULE_NAME            "omapfb-lcd_h2"
+#define TSC2101_UWIRE_CS       1
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int tsc2101_write_reg(int page, int reg, u16 data)
+{
+       u16     cmd;
+       int     r;
+
+       DBGENTER(1);
+
+       cmd = ((page & 3) << 11) | ((reg & 0x3f) << 5);
+       if (omap_uwire_data_transfer(TSC2101_UWIRE_CS, cmd, 16, 0, NULL, 1))
+               r = -1;
+       else
+               r = omap_uwire_data_transfer(TSC2101_UWIRE_CS, data, 16, 0,
+                                            NULL, 0);
+
+       DBGLEAVE(1);
+       return r;
+}
+
+static int h2_panel_init(struct omapfb_device *fbdev)
+{
+       unsigned long uwire_flags;
+       DBGENTER(1);
+
+        /* Configure N15 pin to be uWire CS1 */
+       omap_cfg_reg(N15_1610_UWIRE_CS1);
+       uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
+       uwire_flags |= UWIRE_FREQ_DIV_8;
+       omap_uwire_configure_mode(TSC2101_UWIRE_CS, uwire_flags);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void h2_panel_cleanup(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static int h2_panel_enable(void)
+{
+       int r;
+
+       DBGENTER(1);
+
+       /* Assert LCD_EN, BKLIGHT_EN pins on LCD panel
+        * page2, GPIO config reg, GPIO(0,1) to out and asserted
+        */
+       r = tsc2101_write_reg(2, 0x23, 0xCC00) ? -1 : 0;
+
+       DBGLEAVE(1);
+       return r;
+}
+
+static void h2_panel_disable(void)
+{
+       DBGENTER(1);
+
+       /* Deassert LCD_EN and BKLIGHT_EN pins on LCD panel
+        * page2, GPIO config reg, GPIO(0,1) to out and deasserted
+        */
+       if (tsc2101_write_reg(2, 0x23, 0x8800))
+               pr_err("failed to disable LCD panel\n");
+
+       DBGLEAVE(1);
+}
+
+static unsigned long h2_panel_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_panel h2_panel = {
+       .name           = "h2",
+       .config         = OMAP_LCDC_PANEL_TFT,
+
+       .bpp            = 16,
+       .data_lines     = 16,
+       .x_res          = 240,
+       .y_res          = 320,
+       .pixel_clock    = 5000,
+       .hsw            = 12,
+       .hfp            = 12,
+       .hbp            = 46,
+       .vsw            = 1,
+       .vfp            = 1,
+       .vbp            = 0,
+
+       .init           = h2_panel_init,
+       .cleanup        = h2_panel_cleanup,
+       .enable         = h2_panel_enable,
+       .disable        = h2_panel_disable,
+       .get_caps       = h2_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
new file mode 100644 (file)
index 0000000..78b10c0
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * File: drivers/video/omap/lcd-h3.c
+ *
+ * LCD panel support for the TI OMAP H3 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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/module.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/omapfb.h>
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+
+#define MODULE_NAME    "omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int h3_panel_init(struct omapfb_device *fbdev)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void h3_panel_cleanup(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static int h3_panel_enable(void)
+{
+       int r = 0;
+
+       DBGENTER(1);
+
+       /* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+       r = tps65010_set_gpio_out_value(GPIO1, HIGH);
+       if (!r)
+               r = tps65010_set_gpio_out_value(GPIO2, HIGH);
+       if (r)
+               pr_err("Unable to turn on LCD panel\n");
+
+       DBGLEAVE(1);
+       return r;
+}
+
+static void h3_panel_disable(void)
+{
+       int r = 0;
+
+       DBGENTER(1);
+
+       /* GPIO1 and GPIO2 of TPS65010 send LCD_ENBKL and LCD_ENVDD signals */
+       r = tps65010_set_gpio_out_value(GPIO1, LOW);
+       if (!r)
+               tps65010_set_gpio_out_value(GPIO2, LOW);
+       if (r)
+               pr_err("Unable to turn off LCD panel\n");
+
+       DBGLEAVE(1);
+}
+
+static unsigned long h3_panel_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_panel h3_panel = {
+       .name           = "h3",
+       .config         = OMAP_LCDC_PANEL_TFT,
+
+       .data_lines     = 16,
+       .bpp            = 16,
+       .x_res          = 240,
+       .y_res          = 320,
+       .pixel_clock    = 12500,
+       .hsw            = 12,
+       .hfp            = 14,
+       .hbp            = 72 - 12,
+       .vsw            = 1,
+       .vfp            = 1,
+       .vbp            = 0,
+       .pcd            = 2,
+
+       .init           = h3_panel_init,
+       .cleanup        = h3_panel_cleanup,
+       .enable         = h3_panel_enable,
+       .disable        = h3_panel_disable,
+       .get_caps       = h3_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
new file mode 100644 (file)
index 0000000..4817247
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * File: drivers/video/omap/lcd-h4.c
+ *
+ * LCD panel support for the TI OMAP H4 board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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/module.h>
+
+#include <asm/arch/omapfb.h>
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+
+static int h4_panel_init(struct omapfb_device *fbdev)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void h4_panel_cleanup(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static int h4_panel_enable(void)
+{
+
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void h4_panel_disable(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static unsigned long h4_panel_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_panel h4_panel = {
+       .name           = "h4",
+       .config         = OMAP_LCDC_PANEL_TFT,
+
+       .bpp            = 16,
+       .data_lines     = 16,
+       .x_res          = 240,
+       .y_res          = 320,
+       .pixel_clock    = 6250,
+       .hsw            = 15,
+       .hfp            = 15,
+       .hbp            = 60,
+       .vsw            = 1,
+       .vfp            = 1,
+       .vbp            = 1,
+
+       .init           = h4_panel_init,
+       .cleanup        = h4_panel_cleanup,
+       .enable         = h4_panel_enable,
+       .disable        = h4_panel_disable,
+       .get_caps       = h4_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
new file mode 100644 (file)
index 0000000..d6ae2f6
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * File: drivers/video/omap/lcd-inn1510.c
+ *
+ * LCD panel support for the TI OMAP1510 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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/module.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/omapfb.h>
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+
+static int innovator1510_panel_init(struct omapfb_device *fbdev)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void innovator1510_panel_cleanup(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static int innovator1510_panel_enable(void)
+{
+       DBGENTER(1);
+
+       fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void innovator1510_panel_disable(void)
+{
+       DBGENTER(1);
+
+       fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+
+       DBGLEAVE(1);
+}
+
+static unsigned long innovator1510_panel_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_panel innovator1510_panel = {
+       .name           = "inn1510",
+       .config         = OMAP_LCDC_PANEL_TFT,
+
+       .bpp            = 16,
+       .data_lines     = 16,
+       .x_res          = 240,
+       .y_res          = 320,
+       .pixel_clock    = 12500,
+       .hsw            = 40,
+       .hfp            = 40,
+       .hbp            = 72,
+       .vsw            = 1,
+       .vfp            = 1,
+       .vbp            = 0,
+       .pcd            = 12,
+
+       .init           = innovator1510_panel_init,
+       .cleanup        = innovator1510_panel_cleanup,
+       .enable         = innovator1510_panel_enable,
+       .disable        = innovator1510_panel_disable,
+       .get_caps       = innovator1510_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
new file mode 100644 (file)
index 0000000..bf71485
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * File: drivers/video/omap/lcd-inn1610.c
+ *
+ * LCD panel support for the TI OMAP1610 Innovator board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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/module.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+
+#define MODULE_NAME    "omapfb-lcd_h3"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int innovator1610_panel_init(struct omapfb_device *fbdev)
+{
+       int r = 0;
+
+       DBGENTER(1);
+
+       if (omap_request_gpio(14)) {
+               pr_err("can't request GPIO 14\n");
+               r = -1;
+               goto exit;
+       }
+       if (omap_request_gpio(15)) {
+               pr_err("can't request GPIO 15\n");
+               omap_free_gpio(14);
+               r = -1;
+               goto exit;
+       }
+       /* configure GPIO(14, 15) as outputs */
+       omap_set_gpio_direction(14, 0);
+       omap_set_gpio_direction(15, 0);
+exit:
+       DBGLEAVE(1);
+       return r;
+}
+
+static void innovator1610_panel_cleanup(void)
+{
+       DBGENTER(1);
+
+       omap_free_gpio(15);
+       omap_free_gpio(14);
+
+       DBGLEAVE(1);
+}
+
+static int innovator1610_panel_enable(void)
+{
+       DBGENTER(1);
+
+       /* set GPIO14 and GPIO15 high */
+       omap_set_gpio_dataout(14, 1);
+       omap_set_gpio_dataout(15, 1);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void innovator1610_panel_disable(void)
+{
+       DBGENTER(1);
+
+       /* set GPIO13, GPIO14 and GPIO15 low */
+       omap_set_gpio_dataout(14, 0);
+       omap_set_gpio_dataout(15, 0);
+
+       DBGLEAVE(1);
+}
+
+static unsigned long innovator1610_panel_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_panel innovator1610_panel = {
+       .name           = "inn1610",
+       .config         = OMAP_LCDC_PANEL_TFT,
+
+       .bpp            = 16,
+       .data_lines     = 16,
+       .x_res          = 320,
+       .y_res          = 240,
+       .pixel_clock    = 12500,
+       .hsw            = 40,
+       .hfp            = 40,
+       .hbp            = 72,
+       .vsw            = 1,
+       .vfp            = 1,
+       .vbp            = 0,
+       .pcd            = 12,
+
+       .init           = innovator1610_panel_init,
+       .cleanup        = innovator1610_panel_cleanup,
+       .enable         = innovator1610_panel_enable,
+       .disable        = innovator1610_panel_disable,
+       .get_caps       = innovator1610_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
new file mode 100644 (file)
index 0000000..54808d6
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * File: drivers/video/omap/lcd-osk.c
+ *
+ * LCD panel support for the TI OMAP OSK board
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ * Adapted for OSK by <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 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/module.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+
+static int osk_panel_init(struct omapfb_device *fbdev)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void osk_panel_cleanup(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static int osk_panel_enable(void)
+{
+       DBGENTER(1);
+
+       /* configure PWL pin */
+       omap_cfg_reg(PWL);
+
+       /* Enable PWL unit */
+       omap_writeb(0x01, OMAP16XX_PWL_CLK_ENABLE);
+
+       /* Set PWL level */
+       omap_writeb(0xFF, OMAP16XX_PWL_ENABLE);
+
+       /* configure GPIO2 as output */
+       omap_set_gpio_direction(2, 0);
+
+       /* set GPIO2 high */
+       omap_set_gpio_dataout(2, 1);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void osk_panel_disable(void)
+{
+       DBGENTER(1);
+
+       /* Set PWL level to zero */
+       omap_writeb(0x00, OMAP16XX_PWL_ENABLE);
+
+       /* Disable PWL unit */
+       omap_writeb(0x00, OMAP16XX_PWL_CLK_ENABLE);
+
+       /* set GPIO2 low */
+       omap_set_gpio_dataout(2, 0);
+
+       DBGLEAVE(1);
+}
+
+static unsigned long osk_panel_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_panel osk_panel = {
+       .name           = "osk",
+       .config         = OMAP_LCDC_PANEL_TFT,
+
+       .bpp            = 16,
+       .data_lines     = 16,
+       .x_res          = 240,
+       .y_res          = 320,
+       .pixel_clock    = 12500,
+       .hsw            = 40,
+       .hfp            = 40,
+       .hbp            = 72,
+       .vsw            = 1,
+       .vfp            = 1,
+       .vbp            = 0,
+       .pcd            = 12,
+
+       .init           = osk_panel_init,
+       .cleanup        = osk_panel_cleanup,
+       .enable         = osk_panel_enable,
+       .disable        = osk_panel_disable,
+       .get_caps       = osk_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcd_p2.c b/drivers/video/omap/lcd_p2.c
new file mode 100644 (file)
index 0000000..5a3e2db
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * File: drivers/video/omap/lcd-p2.c
+ *
+ * LCD panel support for the TI OMAP P2 board
+ *
+ * Authors:
+ *   jekyll <jekyll@mail.jekyll.idv.tw>
+ *   B Jp <lastjp_fr@yahoo.fr>
+ *   Brian Swetland <swetland@android.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/module.h>
+#include <linux/delay.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/omapfb.h>
+
+/*
+ * File: epson-md-tft.h
+ *
+ * This file contains definitions for Epsons MD-TF LCD Module
+ *
+ * Copyright (C) 2004 MPC-Data Limited  (http://www.mpc-data.co.uk)
+ * Author: Dave Peverley <dpeverley at mpc-data.co.uk>
+ *
+ *  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.
+ *
+ * Please report all bugs and problems to the author.
+ *
+ */
+
+/* LCD uWire commands & params
+ * All values from Epson
+ */
+#define LCD_DISON 0xAF
+#define LCD_DISOFF 0xAE
+#define LCD_DISNOR 0xA6
+#define LCD_DISINV 0xA7
+#define LCD_DISCTL 0xCA
+#define LCD_GCP64 0xCB
+#define LCD_GCP16 0xCC
+#define LCD_GSSET 0xCD
+#define LCD_SLPIN 0x95
+#define LCD_SLPOUT 0x94
+#define LCD_SD_PSET 0x75
+#define LCD_MD_PSET 0x76
+#define LCD_SD_CSET 0x15
+#define LCD_MD_CSET 0x16
+#define LCD_DATCTL 0xBC
+#define LCD_RAMWR 0x5C
+#define LCD_RAMRD 0x5D
+#define LCD_PTLIN 0xA8
+#define LCD_PTLOUT 0xA9
+#define LCD_ASCSET 0xAA
+#define LCD_SCSTART 0xAB
+#define LCD_VOLCTL 0xC6
+#define LCD_NOP 0x25
+#define LCD_OSCISEL 0x7
+#define LCD_3500KSET 0xD1
+#define LCD_3500KEND 0xD2
+#define LCD_14MSET 0xD3
+#define LCD_14MEND 0xD4
+
+#define INIT_3500KSET 0x45
+#define INIT_14MSET 0x4B
+#define INIT_DATCTL 0x08 /* 6.6.6 bits for D-Sample */
+
+#define INIT_OSCISEL 0x05
+
+#define INIT_VOLCTL 0x77 /* Nominel "volume" */
+
+#define INIT_VOLCTL_Ton 0x98 /* Activate power-IC timer */
+#define INIT_GSSET 0x00
+
+const unsigned short INIT_DISCTL[11] =
+{
+       0xDE, 0x01, 0x64, 0x00, 0x1B, 0xF4, 0x00, 0xDC, 0x00, 0x02, 0x00
+};
+
+const unsigned short INIT_GCP64[126] =
+{
+       0x3B,0x00,0x42,0x00,0x4A,0x00,0x51,0x00,
+       0x58,0x00,0x5F,0x00,0x66,0x00,0x6E,0x00,
+       0x75,0x00,0x7C,0x00,0x83,0x00,0x8A,0x00,
+       0x92,0x00,0x99,0x00,0xA0,0x00,0xA7,0x00,
+       0xAE,0x00,0xB6,0x00,0xBD,0x00,0xC4,0x00,
+       0xCB,0x00,0xD2,0x00,0xDA,0x00,0xE1,0x00,
+       0xE8,0x00,0xEF,0x00,0xF6,0x00,0xFE,0x00,
+       0x05,0x01,0x0C,0x01,0x13,0x01,0x1A,0x01,
+       0x22,0x01,0x29,0x01,0x30,0x01,0x37,0x01,
+       0x3E,0x01,0x46,0x01,0x4D,0x01,0x54,0x01,
+       0x5B,0x01,0x62,0x01,0x6A,0x01,0x71,0x01,
+       0x78,0x01,0x7F,0x01,0x86,0x01,0x8E,0x01,
+       0x95,0x01,0x9C,0x01,0xA3,0x01,0xAA,0x01,
+       0xB2,0x01,0xB9,0x01,0xC0,0x01,0xC7,0x01,
+       0xCE,0x01,0xD6,0x01,0xDD,0x01,0xE4,0x01,
+       0xEB,0x01,0xF2,0x01,0xFA,0x01
+};
+
+const unsigned short INIT_GCP16[15] =
+{
+       0x1A,0x31,0x48,0x54,0x5F,0x67,0x70,0x76,0x7C,0x80,0x83,0x84,0x85,0x87,0x96
+};
+
+const unsigned short INIT_MD_PSET[4] = { 0, 0, 219, 0 };
+const unsigned short INIT_MD_CSET[4] = { 2, 0, 177, 0 };
+
+const unsigned short INIT_SD_PSET[4] = { 0x00, 0x01, 0x00, 0x01 };
+const unsigned short INIT_SD_CSET[4] = { 0x00, 0x02, 0x00, 0x02 };
+
+const unsigned short INIT_ASCSET[7] = { 0x00, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0x01 };
+const unsigned short INIT_SCSTART[2] = { 0x00, 0x00 };
+
+/* ----- end of epson_md_tft.h ----- */
+
+
+#include "debug.h"
+#include "../drivers/ssi/omap-uwire.h"
+
+#define LCD_UWIRE_CS 0
+
+static int p2_panel_init(struct omapfb_device *fbdev)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void p2_panel_cleanup(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static int p2_panel_enable(void)
+{
+       int i;
+       unsigned long value;
+       DBGENTER(1);
+
+               /* thwack the reset line */
+       omap_set_gpio_direction(19, 0);
+       omap_set_gpio_dataout(19, 0);
+       mdelay(2);
+       omap_set_gpio_dataout(19, 1);
+
+               /* bits 31:28 -> 0  LCD_PXL_15 .. 12 */
+       value = omap_readl(OMAP730_IO_CONF_3) & 0x0FFFFFFF;
+       omap_writel(value, OMAP730_IO_CONF_3);
+
+               /* bits 19:0 -> 0  LCD_VSYNC, AC, PXL_0, PCLK, HSYNC,
+               **                 PXL_9..1, PXL_10, PXL_11
+               */
+       value = omap_readl(OMAP730_IO_CONF_4) & 0xFFF00000;
+       omap_writel(value, OMAP730_IO_CONF_4);
+
+       omap_uwire_configure_mode(0,16);
+
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISOFF, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SLPIN, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISNOR, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GSSET, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GSSET | 0x100), 9, 0,NULL,1);
+
+       /* DISCTL */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISCTL, 9, 0,NULL,1);
+       for (i = 0; i < (sizeof(INIT_DISCTL)/sizeof(unsigned short)); i++)
+               omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_DISCTL[i] | 0x100), 9, 0,NULL,1);
+
+       /* GCP64 */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GCP64, 9, 0,NULL,1);
+       for (i = 0; i < (sizeof(INIT_GCP64)/sizeof(unsigned short)); i++)
+               omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GCP64[i] | 0x100), 9, 0,NULL,1);
+
+       /* GCP16 */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_GCP16, 9, 0,NULL,1);
+       for (i = 0; i < (sizeof(INIT_GCP16)/sizeof(unsigned short)); i++)
+               omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_GCP16[i] | 0x100), 9, 0,NULL,1);
+
+       /* MD_CSET */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_MD_CSET, 9, 0,NULL,1);
+       for (i = 0; i < (sizeof(INIT_MD_CSET)/sizeof(unsigned short)); i++)
+               omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_MD_CSET[i] | 0x100), 9, 0,NULL,1);
+
+       /* MD_PSET */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_MD_PSET, 9, 0,NULL,1);
+       for (i = 0; i < (sizeof(INIT_MD_PSET)/sizeof(unsigned short)); i++)
+               omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_MD_PSET[i] | 0x100), 9, 0,NULL,1);
+
+       /* SD_CSET */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SD_CSET, 9, 0,NULL,1);
+       for (i = 0; i < (sizeof(INIT_SD_CSET)/sizeof(unsigned short)); i++)
+               omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_SD_CSET[i] | 0x100), 9, 0,NULL,1);
+
+       /* SD_PSET */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SD_PSET, 9, 0,NULL,1);
+       for (i = 0; i < (sizeof(INIT_SD_PSET)/sizeof(unsigned short)); i++)
+               omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_SD_PSET[i] | 0x100), 9, 0,NULL,1);
+
+       /* DATCTL */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DATCTL, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_DATCTL | 0x100), 9, 0,NULL,1);
+
+       /* OSSISEL = d'5 */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_OSCISEL, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_OSCISEL | 0x100), 9, 0,NULL,1);
+
+       /* 14MSET = d'74 */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_14MSET, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_14MSET | 0x100), 9, 0,NULL,1);
+
+       /* 14MEND */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_14MEND, 9, 0,NULL,1);
+
+       /* 3500KSET = d'69 */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_3500KSET, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_3500KSET | 0x100), 9, 0,NULL,1);
+
+       /* 3500KEND */
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_3500KEND, 9, 0,NULL,1);
+
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_SLPOUT, 9, 0,NULL,1);
+
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_VOLCTL, 9, 0,NULL,1);
+       omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_VOLCTL_Ton | 0x100), 9, 0,NULL,1);
+
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_VOLCTL, 9, 0,NULL,1);
+
+       omap_uwire_data_transfer(LCD_UWIRE_CS, (INIT_VOLCTL | 0x100), 9, 0,NULL,1);
+
+       omap_uwire_data_transfer(LCD_UWIRE_CS, LCD_DISON, 9, 0,NULL,1);
+
+       /* enable backlight */
+       omap_set_gpio_direction(134, 0);
+       omap_set_gpio_dataout(134, 1);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void p2_panel_disable(void)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static unsigned long p2_panel_get_caps(void)
+{
+       return 0;
+}
+
+struct lcd_panel p2_panel = {
+       .name           = "p2",
+       .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_PIX_CLOCK,
+
+       .bpp            = 16,
+       .data_lines     = 16,
+       .x_res          = 176,
+       .y_res          = 220,
+       .pixel_clock    = 12500,
+       .hsw            = 5,
+       .hfp            = 1,
+       .hbp            = 1,
+       .vsw            = 2,
+       .vfp            = 12,
+       .vbp            = 1,
+
+       .init           = p2_panel_init,
+       .cleanup        = p2_panel_cleanup,
+       .enable         = p2_panel_enable,
+       .disable        = p2_panel_disable,
+       .get_caps       = p2_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
new file mode 100644 (file)
index 0000000..3f25b73
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * File: drivers/video/omap/lcd_palmte.c
+ *
+ * LCD panel support for the Palm Tungsten E
+ *
+ * Original version : Romain Goyet
+ * Current version : Laurent Gonzalez
+ *
+ * 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/module.h>
+
+#include <asm/io.h>
+#include <asm/arch/fpga.h>
+
+#include "omapfb.h"
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+
+static int palmte_panel_init(struct lcd_panel *panel)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void palmte_panel_cleanup(struct lcd_panel *panel)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static int palmte_panel_enable(struct lcd_panel *panel)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void palmte_panel_disable(struct lcd_panel *panel)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+}
+
+static unsigned long palmte_panel_get_caps(struct lcd_panel *panel)
+{
+       return 0;
+}
+
+struct lcd_panel palmte_panel = {
+       .name           = "palmte",
+       .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
+                         OMAP_LCDC_INV_HSYNC | OMAP_LCDC_HSVS_RISING_EDGE |
+                         OMAP_LCDC_HSVS_OPPOSITE;
+
+       .data_lines     = 16,
+       .bpp            = 8,
+       .pixel_clock    = 12500,
+       .x_res          = 320,
+       .y_res          = 320,
+       .hsw            = 4,
+       .hfp            = 8,
+       .hbp            = 28,
+       .vsw            = 1,
+       .vfp            = 8,
+       .vbp            = 7,
+       .pcd            = 5,
+
+       .init           = palmte_panel_init,
+       .cleanup        = palmte_panel_cleanup,
+       .enable         = palmte_panel_enable,
+       .disable        = palmte_panel_disable,
+       .get_caps       = palmte_panel_get_caps,
+};
+
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
new file mode 100644 (file)
index 0000000..fd5e137
--- /dev/null
@@ -0,0 +1,708 @@
+/*
+ * File: drivers/video/omap/omap1/lcdc.c
+ *
+ * OMAP1 internal LCD controller
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/omapfb.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware/clock.h>
+
+/* #define OMAPFB_DBG 2 */
+
+#include "debug.h"
+
+#define MODULE_NAME                    "omapfb-lcdc"
+
+#define OMAP_LCDC_BASE                 0xfffec000
+#define OMAP_LCDC_SIZE                 256
+#define OMAP_LCDC_IRQ                  INT_LCD_CTRL
+
+#define OMAP_LCDC_CONTROL              (OMAP_LCDC_BASE + 0x00)
+#define OMAP_LCDC_TIMING0              (OMAP_LCDC_BASE + 0x04)
+#define OMAP_LCDC_TIMING1              (OMAP_LCDC_BASE + 0x08)
+#define OMAP_LCDC_TIMING2              (OMAP_LCDC_BASE + 0x0c)
+#define OMAP_LCDC_STATUS               (OMAP_LCDC_BASE + 0x10)
+#define OMAP_LCDC_SUBPANEL             (OMAP_LCDC_BASE + 0x14)
+#define OMAP_LCDC_LINE_INT             (OMAP_LCDC_BASE + 0x18)
+#define OMAP_LCDC_DISPLAY_STATUS       (OMAP_LCDC_BASE + 0x1c)
+
+#define OMAP_LCDC_STAT_DONE            (1 << 0)
+#define OMAP_LCDC_STAT_VSYNC           (1 << 1)
+#define OMAP_LCDC_STAT_SYNC_LOST       (1 << 2)
+#define OMAP_LCDC_STAT_ABC             (1 << 3)
+#define OMAP_LCDC_STAT_LINE_INT                (1 << 4)
+#define OMAP_LCDC_STAT_FUF             (1 << 5)
+#define OMAP_LCDC_STAT_LOADED_PALETTE  (1 << 6)
+
+#define OMAP_LCDC_CTRL_LCD_EN          (1 << 0)
+#define OMAP_LCDC_CTRL_LCD_TFT         (1 << 7)
+#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL        (1 << 10)
+
+#define OMAP_LCDC_IRQ_VSYNC            (1 << 2)
+#define OMAP_LCDC_IRQ_DONE             (1 << 3)
+#define OMAP_LCDC_IRQ_LOADED_PALETTE   (1 << 4)
+#define OMAP_LCDC_IRQ_LINE_NIRQ                (1 << 5)
+#define OMAP_LCDC_IRQ_LINE             (1 << 6)
+#define OMAP_LCDC_IRQ_MASK             (((1 << 5) - 1) << 2)
+
+#define MAX_PALETTE_SIZE               PAGE_SIZE
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+enum lcdc_load_mode {
+       OMAP_LCDC_LOAD_PALETTE,
+       OMAP_LCDC_LOAD_FRAME,
+       OMAP_LCDC_LOAD_PALETTE_AND_FRAME
+};
+
+static struct omap_lcd_controller {
+       enum omapfb_update_mode update_mode;
+
+       unsigned long           frame_offset;
+       int                     screen_width;
+
+       enum omapfb_color_format        color_mode;
+       int                     bpp;
+       int                     palette_org;
+       int                     palette_code;
+       int                     palette_size;
+
+       unsigned int            irq_mask;
+       struct completion       last_frame_complete;
+       struct completion       palette_load_complete;
+       struct clk              *lcd_ck;
+       struct omapfb_device    *fbdev;
+
+       dma_addr_t              vram_phys;
+       void                    *vram_virt;
+       unsigned long           vram_size;
+} omap_lcdc;
+
+static void inline enable_irqs(int mask)
+{
+       omap_lcdc.irq_mask |= mask;
+}
+
+static void inline disable_irqs(int mask)
+{
+       omap_lcdc.irq_mask &= ~mask;
+}
+
+static void set_load_mode(enum lcdc_load_mode mode)
+{
+       u32 l;
+
+       l = omap_readl(OMAP_LCDC_CONTROL);
+       l &= ~(3 << 20);
+       switch (mode) {
+       case OMAP_LCDC_LOAD_PALETTE:
+               l |= 1 << 20;
+               break;
+       case OMAP_LCDC_LOAD_FRAME:
+               l |= 2 << 20;
+               break;
+       case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:
+               break;
+       default:
+               BUG();
+       }
+       omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void enable_controller(void)
+{
+       u32 l;
+
+       l = omap_readl(OMAP_LCDC_CONTROL);
+       l |= OMAP_LCDC_CTRL_LCD_EN;
+       l &= ~OMAP_LCDC_IRQ_MASK;
+       l |= omap_lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;   /* enabled IRQs */
+       omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller_async(void)
+{
+       u32 l;
+       u32 mask;
+
+       l = omap_readl(OMAP_LCDC_CONTROL);
+       mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;
+       /* Preserve the DONE mask, since we still want to get the
+        * final DONE irq. It will be disabled in the IRQ handler.
+        */
+       mask &= ~OMAP_LCDC_IRQ_DONE;
+       l &= ~mask;
+       omap_writel(l, OMAP_LCDC_CONTROL);
+}
+
+static void disable_controller(void)
+{
+       init_completion(&omap_lcdc.last_frame_complete);
+       disable_controller_async();
+       if (!wait_for_completion_timeout(&omap_lcdc.last_frame_complete,
+                               msecs_to_jiffies(500)))
+               pr_err("timeout waiting for FRAME DONE\n");
+}
+
+static void reset_controller(u32 status)
+{
+       static unsigned long reset_count = 0;
+       static unsigned long last_jiffies = 0;
+
+       disable_controller_async();
+       reset_count++;
+       if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {
+               pr_err("resetting (status %#010x,reset count %lu)\n",
+                         status, reset_count);
+               last_jiffies = jiffies;
+       }
+       if (reset_count < 100) {
+               enable_controller();
+       } else {
+               reset_count = 0;
+               pr_err("too many reset attempts, giving up.\n");
+       }
+}
+
+/* Configure the LCD DMA according to the current mode specified by parameters
+ * in omap_lcdc.fbdev and fbdev->var.
+ */
+static void setup_lcd_dma(void)
+{
+       static const int dma_elem_type[] = {
+               0,
+               OMAP_DMA_DATA_TYPE_S8,
+               OMAP_DMA_DATA_TYPE_S16,
+               0,
+               OMAP_DMA_DATA_TYPE_S32,
+       };
+       struct fb_var_screeninfo *var = &omap_lcdc.fbdev->fb_info->var;
+       struct lcd_panel *panel = omap_lcdc.fbdev->panel;
+       unsigned long   src;
+       int             esize, xelem, yelem;
+
+       src = omap_lcdc.vram_phys + PAGE_ALIGN(MAX_PALETTE_SIZE) +
+               omap_lcdc.frame_offset;
+
+       switch (var->rotate) {
+       case 0:
+               esize = omap_lcdc.fbdev->mirror || (src & 3) ? 2 : 4;
+               xelem = panel->x_res * omap_lcdc.bpp / 8 / esize;
+               yelem = panel->y_res;
+               break;
+       case 90:
+       case 180:
+       case 270:
+               if (cpu_is_omap15xx()) {
+                       BUG();
+               }
+               esize = 2;
+               xelem = panel->y_res * omap_lcdc.bpp / 16;
+               yelem = panel->x_res;
+               break;
+       default:
+               BUG();
+               return;
+       }
+       DBGPRINT(1, "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",
+                src, esize, xelem, yelem);
+       omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);
+       omap_set_lcd_dma_single_transfer(0);
+       if (!cpu_is_omap15xx()) {
+               /* Set virtual xres elem size */
+               omap_set_lcd_dma_b1_vxres(
+                       omap_lcdc.screen_width * omap_lcdc.bpp / 8 / esize);
+               /* Setup transformations */
+               omap_set_lcd_dma_b1_rotation(var->rotate);
+               omap_set_lcd_dma_b1_mirror(omap_lcdc.fbdev->mirror);
+       }
+       omap_setup_lcd_dma();
+}
+
+static irqreturn_t lcdc_irq_handler(int irq, void *dev_id, struct pt_regs *fp)
+{
+       u32 status;
+
+       status = omap_readl(OMAP_LCDC_STATUS);
+
+       if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))
+               reset_controller(status);
+       else {
+               if (status & OMAP_LCDC_STAT_DONE) {
+                       u32 l;
+
+                       /* Disable IRQ_DONE. The status bit will be cleared
+                        * only when the controller is reenabled and we don't
+                        * want to get more interrupts.
+                        */
+                       l = omap_readl(OMAP_LCDC_CONTROL);
+                       l &= ~OMAP_LCDC_IRQ_DONE;
+                       omap_writel(l, OMAP_LCDC_CONTROL);
+                       complete(&omap_lcdc.last_frame_complete);
+               }
+               if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {
+                       disable_controller_async();
+                       complete(&omap_lcdc.palette_load_complete);
+               }
+       }
+
+       /* Clear these interrupt status bits.
+        * Sync_lost, FUF bits were cleared by disabling the LCD controller
+        * LOADED_PALETTE can be cleared this way only in palette only
+        * load mode. In other load modes it's cleared by disabling the
+        * controller.
+        */
+       status &= ~(OMAP_LCDC_STAT_VSYNC |
+                   OMAP_LCDC_STAT_LOADED_PALETTE |
+                   OMAP_LCDC_STAT_ABC |
+                   OMAP_LCDC_STAT_LINE_INT);
+       omap_writel(status, OMAP_LCDC_STATUS);
+       return IRQ_HANDLED;
+}
+
+/* Change to a new video mode. We defer this to a later time to avoid any
+ * flicker and not to mess up the current LCD DMA context. For this we disable
+ * the LCD controler, which will generate a DONE irq after the last frame has
+ * been transferred. Then it'll be safe to reconfigure both the LCD controller
+ * as well as the LCD DMA.
+ */
+static int omap_lcdc_setup_plane(int plane, int channel_out,
+                                unsigned long offset, int screen_width,
+                                int pos_x, int pos_y, int width, int height,
+                                int color_mode)
+{
+       struct fb_var_screeninfo *var = &omap_lcdc.fbdev->fb_info->var;
+       struct lcd_panel *panel = omap_lcdc.fbdev->panel;
+       int rot_x, rot_y;
+
+       DBGENTER(1);
+
+       if (var->rotate == 0) {
+               rot_x = panel->x_res;
+               rot_y = panel->y_res;
+       } else {
+               rot_x = panel->y_res;
+               rot_y = panel->x_res;
+       }
+       if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||
+           width != rot_x || height != rot_y) {
+               DBGPRINT(1, "invalid plane params plane %d pos_x %d "
+                       "pos_y %d w %d h %d\n", plane, pos_x, pos_y,
+                       width, height);
+               return -EINVAL;
+       }
+
+       omap_lcdc.frame_offset = offset;
+       omap_lcdc.screen_width = screen_width;
+       omap_lcdc.color_mode = color_mode;
+
+       switch (color_mode) {
+       case OMAPFB_COLOR_CLUT_8BPP:
+               omap_lcdc.bpp = 8;
+               omap_lcdc.palette_code = 0x3000;
+               omap_lcdc.palette_size = 512;
+               break;
+       case OMAPFB_COLOR_RGB565:
+               omap_lcdc.bpp = 16;
+               omap_lcdc.palette_code = 0x4000;
+               omap_lcdc.palette_size = 32;
+               break;
+       default:
+               /* FIXME: other BPPs.
+                * bpp1: code  0,     size 256
+                * bpp2: code  0x1000 size 256
+                * bpp4: code  0x2000 size 256
+                * bpp12: code 0x4000 size 32
+                */
+               DBGPRINT(1, "invalid color mode %d\n", color_mode);
+               return -1;
+       }
+
+       omap_lcdc.palette_org = PAGE_ALIGN(MAX_PALETTE_SIZE) -
+                                       omap_lcdc.palette_size;
+
+       if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+               disable_controller();
+               omap_stop_lcd_dma();
+               setup_lcd_dma();
+               enable_controller();
+       }
+
+       DBGLEAVE(1);
+
+       return 0;
+}
+
+static int omap_lcdc_enable_plane(int plane, int enable)
+{
+       if (plane != 0 || enable != 1)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* Configure the LCD DMA for a palette load operation and do the palette
+ * downloading synchronously. We don't use the frame+palette load mode of
+ * the controller, since the palette can always be downloaded seperately.
+ */
+static void load_palette(void)
+{
+       u16     *palette;
+
+       DBGENTER(1);
+
+       palette = (u16 *)((u8 *)omap_lcdc.vram_virt + omap_lcdc.palette_org);
+
+       *(u16 *)palette &= 0x0fff;
+       *(u16 *)palette |= omap_lcdc.palette_code;
+
+       omap_set_lcd_dma_b1(omap_lcdc.vram_phys + omap_lcdc.palette_org,
+               omap_lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);
+
+       omap_set_lcd_dma_single_transfer(1);
+       omap_setup_lcd_dma();
+
+       init_completion(&omap_lcdc.palette_load_complete);
+       enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+       set_load_mode(OMAP_LCDC_LOAD_PALETTE);
+       enable_controller();
+       if (!wait_for_completion_timeout(&omap_lcdc.palette_load_complete,
+                               msecs_to_jiffies(500)))
+               pr_err("timeout waiting for FRAME DONE\n");
+       /* The controller gets disabled in the irq handler */
+       disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);
+       omap_stop_lcd_dma();
+
+       DBGLEAVE(1);
+}
+
+static void calc_ck_div(int is_tft, int pck, int *pck_div)
+{
+       unsigned long lck;
+
+       pck = max(1, pck);
+       lck = clk_get_rate(omap_lcdc.lcd_ck);
+       *pck_div = lck / pck;
+       if (is_tft)
+               *pck_div = max(2, *pck_div);
+       else
+               *pck_div = max(3, *pck_div);
+       if (*pck_div > 255) {
+               /* FIXME: try to adjust logic clock divider as well */
+               *pck_div = 255;
+               printk(KERN_WARNING MODULE_NAME ": pixclock %d kHz too low.\n",
+                               pck / 1000);
+       }
+}
+
+static void inline setup_regs(void)
+{
+       u32 l;
+       struct lcd_panel *panel = omap_lcdc.fbdev->panel;
+       int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
+       unsigned long lck;
+       int pcd;
+
+       l = omap_readl(OMAP_LCDC_CONTROL);
+       l &= ~OMAP_LCDC_CTRL_LCD_TFT;
+       l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;
+#ifdef CONFIG_MACH_OMAP_PALMTE
+/* FIXME:if (machine_is_omap_palmte()) { */
+               /* PalmTE uses alternate TFT setting in 8BPP mode */
+               l |= (tft && fbdev->panel->video_mode->bpp == 8) ? 0x810000 : 0;
+/*     } */
+#endif
+       omap_writel(l, OMAP_LCDC_CONTROL);
+
+       l = omap_readl(OMAP_LCDC_TIMING2);
+       l &= ~(((1 << 6) - 1) << 20);
+       l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;
+       omap_writel(l, OMAP_LCDC_TIMING2);
+
+       l = panel->x_res - 1;
+       l |= (panel->hsw - 1) << 10;
+       l |= (panel->hfp - 1) << 16;
+       l |= (panel->hbp - 1) << 24;
+       omap_writel(l, OMAP_LCDC_TIMING0);
+
+       l = panel->y_res - 1;
+       l |= (panel->vsw - 1) << 10;
+       l |= panel->vfp << 16;
+       l |= panel->vbp << 24;
+       omap_writel(l, OMAP_LCDC_TIMING1);
+
+       l = omap_readl(OMAP_LCDC_TIMING2);
+       l &= ~0xff;
+
+       lck = clk_get_rate(omap_lcdc.lcd_ck);
+
+       if (!panel->pcd)
+               calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);
+       else {
+               printk(KERN_WARNING
+                   MODULE_NAME ": Pixel clock divider value is obsolete.\n"
+                   MODULE_NAME ": Try to set pixel_clock to %lu and pcd to 0 "
+                   "in drivers/video/omap/lcd_%s.c and submit a patch.\n",
+                       lck / panel->pcd / 1000, panel->name);
+
+               pcd = panel->pcd;
+       }
+       l |= pcd & 0xff;
+       l |= panel->acb << 8;
+       omap_writel(l, OMAP_LCDC_TIMING2);
+
+       /* update panel info with the exact clock */
+       panel->pixel_clock = lck / pcd / 1000;
+}
+
+/* Configure the LCD controller, download the color palette and start a looped
+ * DMA transfer of the frame image data. */
+static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)
+{
+       int r = 0;
+
+       DBGENTER(1);
+
+       if (mode != omap_lcdc.update_mode) {
+               switch (mode) {
+               case OMAPFB_AUTO_UPDATE:
+                       setup_regs();
+                       load_palette();
+
+                       /* Setup and start LCD DMA */
+                       setup_lcd_dma();
+
+                       set_load_mode(OMAP_LCDC_LOAD_FRAME);
+                       enable_irqs(OMAP_LCDC_IRQ_DONE);
+                       /* This will start the actual DMA transfer */
+                       enable_controller();
+                       omap_lcdc.update_mode = mode;
+                       break;
+               case OMAPFB_UPDATE_DISABLED:
+                       disable_controller();
+                       omap_stop_lcd_dma();
+                       omap_lcdc.update_mode = mode;
+                       break;
+               default:
+                       r = -EINVAL;
+               }
+       }
+
+       DBGLEAVE(1);
+       return r;
+}
+
+static enum omapfb_update_mode omap_lcdc_get_update_mode(void)
+{
+       return omap_lcdc.update_mode;
+}
+
+static void omap_lcdc_suspend(void)
+{
+       if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+               disable_controller();
+               omap_stop_lcd_dma();
+       }
+}
+
+static void omap_lcdc_resume(void)
+{
+       if (omap_lcdc.update_mode == OMAPFB_AUTO_UPDATE) {
+               setup_regs();
+               load_palette();
+               setup_lcd_dma();
+               set_load_mode(OMAP_LCDC_LOAD_FRAME);
+               enable_irqs(OMAP_LCDC_IRQ_DONE);
+               enable_controller();
+       }
+}
+
+static void omap_lcdc_get_vram_layout(unsigned long *size, void **virt,
+                                       dma_addr_t *phys)
+{
+       *size = omap_lcdc.vram_size - PAGE_ALIGN(MAX_PALETTE_SIZE);
+       *virt = (u8 *)omap_lcdc.vram_virt + PAGE_ALIGN(MAX_PALETTE_SIZE);
+       *phys = omap_lcdc.vram_phys + PAGE_ALIGN(MAX_PALETTE_SIZE);
+}
+
+static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
+                         int req_vram_size)
+{
+       int r;
+       u32 l;
+       int rate;
+       struct clk *tc_ck;
+       struct lcd_panel *panel = fbdev->panel;
+       int frame_size;
+
+       DBGENTER(1);
+
+       omap_lcdc.irq_mask = 0;
+
+       omap_lcdc.fbdev = fbdev;
+
+       pr_info(MODULE_NAME ": init\n");
+
+       l = 0;
+       omap_writel(l, OMAP_LCDC_CONTROL);
+
+       /* FIXME:
+        * According to errata some platforms have a clock rate limitiation
+        */
+       omap_lcdc.lcd_ck = clk_get(NULL, "lcd_ck");
+       if (IS_ERR(omap_lcdc.lcd_ck)) {
+               pr_err("unable to access LCD clock\n");
+               r = PTR_ERR(omap_lcdc.lcd_ck);
+               goto fail0;
+       }
+
+       tc_ck = clk_get(NULL, "tc_ck");
+       if (IS_ERR(tc_ck)) {
+               pr_err("unable to access TC clock\n");
+               r = PTR_ERR(tc_ck);
+               goto fail1;
+       }
+
+       rate = clk_get_rate(tc_ck);
+       clk_put(tc_ck);
+
+       if (machine_is_omap_h3())
+               rate /= 3;
+       r = clk_set_rate(omap_lcdc.lcd_ck, rate);
+       if (r) {
+               pr_err("failed to adjust LCD rate\n");
+               goto fail1;
+       }
+       clk_use(omap_lcdc.lcd_ck);
+
+       r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, "omap-lcdc",
+                       omap_lcdc.fbdev);
+       if (r) {
+               pr_err("unable to get IRQ\n");
+               goto fail2;
+       }
+
+       r = omap_request_lcd_dma(NULL, NULL);
+       if (r) {
+               pr_err("unable to get LCD DMA\n");
+               goto fail3;
+       }
+
+       frame_size = panel->x_res * panel->bpp * panel->y_res / 8;
+       if (req_vram_size > frame_size)
+               frame_size = req_vram_size;
+       omap_lcdc.vram_size = PAGE_ALIGN(MAX_PALETTE_SIZE) + frame_size;
+       omap_lcdc.vram_virt = dma_alloc_writecombine(fbdev->dev,
+                       omap_lcdc.vram_size, &omap_lcdc.vram_phys, GFP_KERNEL);
+
+       if (omap_lcdc.vram_virt == NULL) {
+               pr_err("unable to allocate fb DMA memory\n");
+               r = -ENOMEM;
+               goto fail4;
+       }
+
+       DBGLEAVE(1);
+       return 0;
+fail4:
+       omap_free_lcd_dma();
+fail3:
+       free_irq(OMAP_LCDC_IRQ, omap_lcdc.fbdev);
+fail2:
+       clk_unuse(omap_lcdc.lcd_ck);
+fail1:
+       clk_put(omap_lcdc.lcd_ck);
+fail0:
+       DBGLEAVE(1);
+        return r;
+}
+
+static void omap_lcdc_cleanup(void)
+{
+       dma_free_writecombine(omap_lcdc.fbdev->dev, omap_lcdc.vram_size,
+                             omap_lcdc.vram_virt, omap_lcdc.vram_phys);
+       omap_free_lcd_dma();
+       free_irq(OMAP_LCDC_IRQ, omap_lcdc.fbdev);
+       clk_unuse(omap_lcdc.lcd_ck);
+       clk_put(omap_lcdc.lcd_ck);
+}
+
+static unsigned long omap_lcdc_get_caps(void)
+{
+       return 0;
+}
+
+static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,
+                              u16 transp, int update_hw_pal)
+{
+       u16 *palette;
+
+       if (omap_lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)
+               return -EINVAL;
+
+       palette = (u16 *)((u8*)omap_lcdc.vram_virt +
+                       PAGE_ALIGN(MAX_PALETTE_SIZE) - omap_lcdc.palette_size);
+
+       palette[regno] &= ~0x0fff;
+       palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |
+                          (blue >> 12);
+
+       if (update_hw_pal) {
+               disable_controller();
+               omap_stop_lcd_dma();
+               load_palette();
+               setup_lcd_dma();
+               set_load_mode(OMAP_LCDC_LOAD_FRAME);
+               enable_controller();
+       }
+
+       return 0;
+}
+
+struct lcd_ctrl omap1_int_ctrl = {
+       .name                   = "internal",
+       .init                   = omap_lcdc_init,
+       .cleanup                = omap_lcdc_cleanup,
+       .get_vram_layout        = omap_lcdc_get_vram_layout,
+       .get_caps               = omap_lcdc_get_caps,
+       .set_update_mode        = omap_lcdc_set_update_mode,
+       .get_update_mode        = omap_lcdc_get_update_mode,
+       .update_window          = NULL,
+       .suspend                = omap_lcdc_suspend,
+       .resume                 = omap_lcdc_resume,
+       .setup_plane            = omap_lcdc_setup_plane,
+       .enable_plane           = omap_lcdc_enable_plane,
+       .setcolreg              = omap_lcdc_setcolreg,
+};
+
+MODULE_DESCRIPTION("TI OMAP LCDC controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
new file mode 100644 (file)
index 0000000..58af600
--- /dev/null
@@ -0,0 +1,1511 @@
+/*
+ * File: drivers/video/omap/omapfb_main.c
+ *
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * Acknowledgements:
+ *   Alex McMains <aam@ridgerun.com>       - Original driver
+ *   Juha Yrjola <juha.yrjola@nokia.com>   - Original driver and improvements
+ *   Dirk Behme <dirk.behme@de.bosch.com>  - changes for 2.6 kernel API
+ *   Texas Instruments                     - H3 support
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/board.h>
+#include <asm/arch/omapfb.h>
+
+/* #define OMAPFB_DBG 1 */
+
+#include "debug.h"
+
+#define OMAPFB_DRIVER  "omapfb"
+#define MODULE_NAME    "omapfb"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static unsigned int    def_accel;
+static unsigned long   def_vram;
+static unsigned long   def_vxres;
+static unsigned long   def_vyres;
+static unsigned int    def_rotate;
+static unsigned int    def_mirror;
+
+#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
+static int             manual_update = 1;
+#else
+static int             manual_update;
+#endif
+
+static struct caps_table_struct {
+        unsigned long flag;
+        const char *name;
+} omapfb_caps_table[] = {
+       { OMAPFB_CAPS_MANUAL_UPDATE, "manual update" },
+       { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" },
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD panel
+ * ---------------------------------------------------------------------------
+ */
+extern struct lcd_panel h4_panel;
+extern struct lcd_panel h3_panel;
+extern struct lcd_panel h2_panel;
+extern struct lcd_panel p2_panel;
+extern struct lcd_panel osk_panel;
+extern struct lcd_panel palmte_panel;
+extern struct lcd_panel innovator1610_panel;
+extern struct lcd_panel innovator1510_panel;
+extern struct lcd_panel lph8923_panel;
+
+static struct lcd_panel *panels[] = {
+#ifdef CONFIG_MACH_OMAP_H2
+       &h2_panel,
+#endif
+#ifdef CONFIG_MACH_OMAP_H3
+       &h3_panel,
+#endif
+#ifdef CONFIG_MACH_OMAP_H4
+       &h4_panel,
+#endif
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+       &p2_panel,
+#endif
+#ifdef CONFIG_MACH_OMAP_OSK
+       &osk_panel,
+#endif
+#ifdef CONFIG_MACH_OMAP_PALMTE
+       &palmte_panel,
+#endif
+
+#ifdef CONFIG_MACH_OMAP_INNOVATOR
+
+#ifdef CONFIG_ARCH_OMAP15XX
+       &innovator1510_panel,
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       &innovator1610_panel,
+#endif
+
+#endif
+};
+
+extern struct lcd_ctrl omap1_int_ctrl;
+extern struct lcd_ctrl omap2_int_ctrl;
+extern struct lcd_ctrl hwa742_ctrl;
+extern struct lcd_ctrl blizzard_ctrl;
+
+static struct lcd_ctrl *ctrls[] = {
+#ifdef CONFIG_FB_OMAP_LCDC_INTERNAL
+#ifdef CONFIG_ARCH_OMAP1
+       &omap1_int_ctrl,
+#else
+       &omap2_int_ctrl,
+#endif
+#endif
+};
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+#ifdef CONFIG_ARCH_OMAP1
+extern struct lcd_ctrl_extif sossi_extif;
+#else
+extern struct lcd_ctrl_extif rfbi_extif;
+#endif
+#endif
+
+static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
+{
+       down(&fbdev->rqueue_sema);
+}
+
+static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
+{
+       up(&fbdev->rqueue_sema);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LCD controller and LCD DMA
+ * ---------------------------------------------------------------------------
+ */
+/* Lookup table to map elem size to elem type. */
+static const int dma_elem_type[] = {
+       0,
+       OMAP_DMA_DATA_TYPE_S8,
+       OMAP_DMA_DATA_TYPE_S16,
+       0,
+       OMAP_DMA_DATA_TYPE_S32,
+};
+
+/* Allocate resources needed for LCD controller and LCD DMA operations. Video
+ * memory is allocated from system memory according to the virtual display
+ * size, except if a bigger memory size is specified explicitly as a kernel
+ * parameter.
+ */
+static int ctrl_init(struct omapfb_device *fbdev)
+{
+       int r;
+
+       DBGENTER(1);
+
+       r = fbdev->ctrl->init(fbdev, 0, def_vram);
+       if (r < 0) {
+               pr_err("controller initialization failed\n");
+               goto exit;
+       }
+
+       fbdev->ctrl->get_vram_layout(&fbdev->vram_size, &fbdev->vram_virt_base,
+                                    &fbdev->vram_phys_base);
+       memset((void *)fbdev->vram_virt_base, 0, fbdev->vram_size);
+
+       DBGPRINT(1, "vram_phys %08x vram_virt %p vram_size=%lu\n",
+                fbdev->vram_phys_base, fbdev->vram_virt_base,
+                fbdev->vram_size);
+
+       DBGLEAVE(1);
+       return 0;
+exit:
+       DBGLEAVE(1);
+       return r;
+}
+
+static void ctrl_cleanup(struct omapfb_device *fbdev)
+{
+       fbdev->ctrl->cleanup();
+}
+
+static int ctrl_change_mode(struct omapfb_device *fbdev)
+{
+       int r;
+       unsigned long offset;
+       struct fb_var_screeninfo *var = &fbdev->fb_info->var;
+
+       DBGPRINT(1, "xoffset %d yoffset %d line_length %d bits_per_pixel %d\n",
+               var->xoffset, var->yoffset, fbdev->fb_info->fix.line_length,
+               var->bits_per_pixel);
+       offset = var->yoffset * fbdev->fb_info->fix.line_length +
+                var->xoffset * var->bits_per_pixel / 8;
+       r = fbdev->ctrl->setup_plane(OMAPFB_PLANE_GFX, OMAPFB_CHANNEL_OUT_LCD,
+                                offset, var->xres_virtual, 0, 0, var->xres,
+                                var->yres, fbdev->color_mode);
+       DBGLEAVE(1);
+
+       return r;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks and the ioctl interface
+ * ---------------------------------------------------------------------------
+ */
+/* Called each time the omapfb device is opened */
+static int omapfb_open(struct fb_info *info, int user)
+{
+       DBGENTER(1);
+       DBGLEAVE(1);
+       return 0;
+}
+
+static void omapfb_sync(struct fb_info *info);
+
+/* Called when the omapfb device is closed. We make sure that any pending
+ * gfx DMA operations are ended, before we return. */
+static int omapfb_release(struct fb_info *info, int user)
+{
+       DBGENTER(1);
+
+       omapfb_sync(info);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
+                       u_int blue, u_int transp, int update_hw_pal)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)info->par;
+       int r = 0;
+
+       switch (fbdev->color_mode) {
+       case OMAPFB_COLOR_YUV422:
+       case OMAPFB_COLOR_YUV420:
+               r = -EINVAL;
+               break;
+       case OMAPFB_COLOR_CLUT_8BPP:
+       case OMAPFB_COLOR_CLUT_4BPP:
+       case OMAPFB_COLOR_CLUT_2BPP:
+       case OMAPFB_COLOR_CLUT_1BPP:
+               if (fbdev->ctrl->setcolreg)
+                       r = fbdev->ctrl->setcolreg(regno, red, green, blue,
+                                                       transp, update_hw_pal);
+               /* Fallthrough */
+       case OMAPFB_COLOR_RGB565:
+               if (r != 0)
+                       break;
+
+               if (regno < 0) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               if (regno < 16) {
+                       u16 pal;
+                       pal = ((red >> 11) << 11) | ((green >> 10) << 5) |
+                               (blue >> 11);
+                       ((u32 *)(info->pseudo_palette))[regno] = pal;
+               }
+               break;
+       default:
+               BUG();
+       }
+       return r;
+}
+
+static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                           u_int transp, struct fb_info *info)
+{
+       int r = 0;
+
+       DBGENTER(2);
+
+       _setcolreg(info, regno, red, green, blue, transp, 1);
+
+       DBGLEAVE(2);
+
+       return r;
+}
+
+static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+       int count, index, r;
+       u16 *red, *green, *blue, *transp;
+       u16 trans = 0xffff;
+
+       red     = cmap->red;
+       green   = cmap->green;
+       blue    = cmap->blue;
+       transp  = cmap->transp;
+       index   = cmap->start;
+
+       for (count = 0; count < cmap->len; count++) {
+               if (transp)
+                       trans = *transp++;
+               r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+                               count == cmap->len - 1);
+               if (r != 0)
+                       return r;
+       }
+
+       return 0;
+}
+
+
+static void omapfb_update_full_screen(struct omapfb_device *fbdev);
+
+static int omapfb_blank(int blank, struct fb_info *fbi)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+       int r = 0;
+
+       DBGENTER(1);
+
+       omapfb_rqueue_lock(fbdev);
+       switch (blank) {
+       case VESA_NO_BLANKING:
+               if (fbdev->state == OMAPFB_SUSPENDED) {
+                       fbdev->panel->enable();
+                       if (fbdev->ctrl->resume)
+                               fbdev->ctrl->resume();
+                       fbdev->state = OMAPFB_ACTIVE;
+                       if (fbdev->ctrl->get_update_mode() ==
+                                       OMAPFB_MANUAL_UPDATE)
+                               omapfb_update_full_screen(fbdev);
+               }
+               break;
+       case VESA_POWERDOWN:
+               if (fbdev->state == OMAPFB_ACTIVE) {
+                       if (fbdev->ctrl->suspend)
+                               fbdev->ctrl->suspend();
+                       fbdev->panel->disable();
+                       fbdev->state = OMAPFB_SUSPENDED;
+               }
+               break;
+       default:
+               r = -EINVAL;
+       }
+       omapfb_rqueue_unlock(fbdev);
+
+       DBGLEAVE(1);
+       return r;
+}
+
+static void omapfb_sync(struct fb_info *fbi)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+
+       omapfb_rqueue_lock(fbdev);
+       if (fbdev->ctrl->sync)
+               fbdev->ctrl->sync();
+       omapfb_rqueue_unlock(fbdev);
+}
+
+/* Set fb_info.fix fields and also updates fbdev.
+ * When calling this fb_info.var must be set up already.
+ */
+static void set_fb_fix(struct omapfb_device *fbdev)
+{
+       struct fb_info           *fbi = fbdev->fb_info;
+       struct fb_fix_screeninfo *fix = &fbi->fix;
+       struct fb_var_screeninfo *var = &fbi->var;
+
+       strncpy(fix->id, OMAPFB_DRIVER, sizeof(fix->id));
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       switch (var->bits_per_pixel) {
+       case 16:
+               fix->visual = FB_VISUAL_TRUECOLOR;
+               break;
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+               break;
+       }
+       fix->accel              = FB_ACCEL_OMAP1610;
+       fix->line_length        = var->xres_virtual * var->bits_per_pixel / 8;
+       fix->smem_len           = fbdev->vram_size;
+       fix->smem_start         = fbdev->vram_phys_base;
+}
+
+/* Check the values in var against our capabilities and in case of out of
+ * bound values try to adjust them.
+ */
+static int set_fb_var(struct omapfb_device *fbdev,
+                     struct fb_var_screeninfo *var)
+{
+       int             bpp;
+       unsigned long   max_frame_size;
+       unsigned long   line_size;
+       struct lcd_panel *panel = fbdev->panel;
+
+       bpp = var->bits_per_pixel = panel->bpp;
+
+       switch (bpp) {
+       case 16:
+               fbdev->color_mode = OMAPFB_COLOR_RGB565;
+               break;
+       case 8:
+               fbdev->color_mode = OMAPFB_COLOR_CLUT_8BPP;
+               break;
+       default:
+               /* FIXME: other BPPs not yet supported */
+               return -EINVAL;
+       }
+
+       switch (var->rotate) {
+       case 0:
+       case 180:
+               var->xres = fbdev->panel->x_res;
+               var->yres = fbdev->panel->y_res;
+               break;
+       case 90:
+       case 270:
+               var->xres = fbdev->panel->y_res;
+               var->yres = fbdev->panel->x_res;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (var->xres_virtual < var->xres)
+               var->xres_virtual = var->xres;
+       if (var->yres_virtual < var->yres)
+               var->yres_virtual = var->yres;
+       max_frame_size = fbdev->vram_size;
+       line_size = var->xres_virtual * bpp / 8;
+       if (line_size * var->yres_virtual > max_frame_size) {
+               /* Try to keep yres_virtual first */
+               line_size = max_frame_size / var->yres_virtual;
+               var->xres_virtual = line_size * 8 / bpp;
+               if (var->xres_virtual < var->xres) {
+                       /* Still doesn't fit. Shrink yres_virtual too */
+                       var->xres_virtual = var->xres;
+                       line_size = var->xres * bpp / 8;
+                       var->yres_virtual = max_frame_size / line_size;
+               }
+       }
+       if (var->xres + var->xoffset > var->xres_virtual)
+               var->xoffset = var->xres_virtual - var->xres;
+       if (var->yres + var->yoffset > var->yres_virtual)
+               var->yoffset = var->yres_virtual - var->yres;
+       line_size = var->xres * bpp / 8;
+
+       var->red.offset  = 11; var->red.length   = 5; var->red.msb_right   = 0;
+       var->green.offset= 5;  var->green.length = 6; var->green.msb_right = 0;
+       var->blue.offset = 0;  var->blue.length  = 5; var->blue.msb_right  = 0;
+
+       var->height             = -1;
+       var->width              = -1;
+       var->grayscale          = 0;
+       var->nonstd             = 0;
+
+       /* pixclock in ps, the rest in pixclock */
+       var->pixclock           = 10000000 / (panel->pixel_clock / 100);
+       var->left_margin        = panel->hfp;
+       var->right_margin       = panel->hbp;
+       var->upper_margin       = panel->vfp;
+       var->lower_margin       = panel->vbp;
+       var->hsync_len          = panel->hsw;
+       var->vsync_len          = panel->vsw;
+
+       /* TODO: get these from panel->config */
+       var->vmode              = FB_VMODE_NONINTERLACED;
+       var->sync               = 0;
+
+       return 0;
+}
+
+static struct fb_var_screeninfo new_var;
+
+/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
+static void omapfb_rotate(struct fb_info *fbi, int rotate)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+
+       DBGENTER(1);
+
+       if (cpu_is_omap1510() && rotate != fbdev->fb_info->var.rotate) {
+               memcpy(&new_var, &fbi->var, sizeof(new_var));
+               new_var.rotate = rotate;
+               if (set_fb_var(fbdev, &new_var) == 0 &&
+                   memcmp(&new_var, &fbi->var, sizeof(new_var))) {
+                       memcpy(&fbi->var, &new_var, sizeof(new_var));
+                       ctrl_change_mode(fbdev);
+               }
+       }
+
+       DBGLEAVE(1);
+}
+
+/* Set new x,y offsets in the virtual display for the visible area and switch
+ * to the new mode.
+ */
+static int omapfb_pan_display(struct fb_var_screeninfo *var,
+                              struct fb_info *fbi)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+       int r = 0;
+
+       DBGENTER(1);
+
+       if (var->xoffset != fbi->var.xoffset ||
+           var->yoffset != fbi->var.yoffset) {
+               memcpy(&new_var, &fbi->var, sizeof(new_var));
+               new_var.xoffset = var->xoffset;
+               new_var.yoffset = var->yoffset;
+               if (set_fb_var(fbdev, &new_var))
+                       r = -EINVAL;
+               else {
+                       memcpy(&fbi->var, &new_var, sizeof(new_var));
+                       ctrl_change_mode(fbdev);
+               }
+       }
+
+       DBGLEAVE(1);
+       return r;
+}
+
+/* Set mirror to vertical axis and switch to the new mode. */
+static int omapfb_mirror(struct omapfb_device *fbdev, int mirror)
+{
+       int r = 0;
+
+       DBGENTER(1);
+
+       mirror = mirror ? 1 : 0;
+       if (cpu_is_omap1510())
+               r = -EINVAL;
+       else if (mirror != fbdev->mirror) {
+               fbdev->mirror = mirror;
+               r = ctrl_change_mode(fbdev);
+       }
+
+       DBGLEAVE(1);
+       return r;
+}
+
+/* Check values in var, try to adjust them in case of out of bound values if
+ * possible, or return error.
+ */
+static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+       int r;
+
+       DBGENTER(1);
+
+       r = set_fb_var(fbdev, var);
+
+       DBGLEAVE(1);
+       return r;
+}
+
+/* Switch to a new mode. The parameters for it has been check already by
+ * omapfb_check_var.
+ */
+static int omapfb_set_par(struct fb_info *fbi)
+{
+       int r;
+       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+
+       DBGENTER(1);
+
+       set_fb_fix(fbdev);
+       r = ctrl_change_mode(fbdev);
+
+       DBGLEAVE(1);
+       return r;
+}
+
+static int omapfb_update_win(struct omapfb_device *fbdev,
+                               struct omapfb_update_window *win)
+{
+       struct fb_var_screeninfo *var = &fbdev->fb_info->var;
+       int ret;
+
+       if (win->x >= var->xres || win->y >= var->yres)
+               return -EINVAL;
+
+       if (!fbdev->ctrl->update_window ||
+           fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
+               return -ENODEV;
+
+       if (win->x + win->width >= var->xres)
+               win->width = var->xres - win->x;
+       if (win->y + win->height >= var->yres)
+               win->height = var->yres - win->y;
+       if (!win->width || !win->height)
+               return 0;
+
+       omapfb_rqueue_lock(fbdev);
+       ret = fbdev->ctrl->update_window(win, NULL, 0);
+       omapfb_rqueue_unlock(fbdev);
+
+       return ret;
+}
+
+static void omapfb_update_full_screen(struct omapfb_device *fbdev)
+{
+       struct omapfb_update_window win;
+
+       win.x = 0;
+       win.y = 0;
+       win.width = fbdev->panel->x_res;
+       win.height = fbdev->panel->y_res;
+       win.format = 0;
+
+       omapfb_rqueue_lock(fbdev);
+       fbdev->ctrl->update_window(&win, NULL, 0);
+       omapfb_rqueue_unlock(fbdev);
+}
+
+static int omapfb_setup_plane(struct omapfb_device *fbdev,
+                             struct omapfb_setup_plane *sp)
+{
+       int r;
+
+       omapfb_rqueue_lock(fbdev);
+       r = fbdev->ctrl->setup_plane(sp->plane, sp->channel_out, sp->offset,
+                                sp->width, sp->pos_x, sp->pos_y, sp->width,
+                                sp->height, sp->color_mode);
+       omapfb_rqueue_unlock(fbdev);
+
+       return r;
+}
+
+static int omapfb_enable_plane(struct omapfb_device *fbdev, int plane,
+                               int enable)
+{
+       int r;
+
+       omapfb_rqueue_lock(fbdev);
+       r = fbdev->ctrl->enable_plane(plane, enable);
+       omapfb_rqueue_unlock(fbdev);
+
+       return r;
+}
+
+static int omapfb_set_color_key(struct omapfb_device *fbdev,
+                               struct omapfb_color_key *ck)
+{
+       int r;
+
+       if (!fbdev->ctrl->set_color_key)
+               return -ENODEV;
+
+       omapfb_rqueue_lock(fbdev);
+       r = fbdev->ctrl->set_color_key(ck);
+       omapfb_rqueue_unlock(fbdev);
+
+       return r;
+}
+
+static int omapfb_set_update_mode(struct omapfb_device *fbdev,
+                                  enum omapfb_update_mode mode)
+{
+       int r;
+
+       omapfb_rqueue_lock(fbdev);
+       r = fbdev->ctrl->set_update_mode(mode);
+       omapfb_rqueue_unlock(fbdev);
+
+       return r;
+}
+
+static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
+{
+       int r;
+
+       omapfb_rqueue_lock(fbdev);
+       r = fbdev->ctrl->get_update_mode();
+       omapfb_rqueue_unlock(fbdev);
+
+       return r;
+}
+
+static unsigned long omapfb_get_caps(struct fb_info *fbi)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
+       unsigned long caps;
+
+       caps = 0;
+       caps |= fbdev->panel->get_caps();
+       caps |= fbdev->ctrl->get_caps();
+       return caps;
+}
+
+/* For lcd testing */
+void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
+{
+       omapfb_rqueue_lock(fbdev);
+       *(u16 *)fbdev->vram_virt_base = pixval;
+       if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
+               struct omapfb_update_window win;
+
+               win.x = 0;
+               win.y = 0;
+               win.width = 1;
+               win.height = 1;
+               win.format = 0;
+               fbdev->ctrl->update_window(&win, NULL, 0);
+       }
+       omapfb_rqueue_unlock(fbdev);
+}
+EXPORT_SYMBOL(omapfb_write_first_pixel);
+
+/* Ioctl interface. Part of the kernel mode frame buffer API is duplicated
+ * here to be accessible by user mode code. In addition transparent copy
+ * graphics transformations, frame flipping support is provided through this
+ * interface.
+ */
+static int omapfb_ioctl(struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long arg,
+                       struct fb_info *fbi)
+{
+       struct omapfb_device    *fbdev = (struct omapfb_device *)fbi->par;
+       struct fb_ops           *ops = fbi->fbops;
+       union {
+               struct omapfb_update_window     update_window;
+               struct omapfb_setup_plane       setup_plane;
+               struct omapfb_enable_plane      enable_plane;
+               struct omapfb_color_key         color_key;
+               enum omapfb_update_mode         update_mode;
+               unsigned long           caps;
+               unsigned int            mirror;
+       } p;
+       int r = 0;
+
+       DBGENTER(2);
+
+       BUG_ON(!ops);
+       DBGPRINT(2, "cmd=%010x\n", cmd);
+       switch (cmd)
+       {
+       case OMAPFB_MIRROR:
+               if (get_user(p.mirror, (int __user *)arg))
+                       r = -EFAULT;
+               else
+                       omapfb_mirror(fbdev, p.mirror);
+               break;
+       case OMAPFB_SYNC_GFX:
+               omapfb_sync(fbi);
+               break;
+       case OMAPFB_VSYNC:
+               break;
+       case OMAPFB_SET_UPDATE_MODE:
+               if (get_user(p.update_mode, (int __user *)arg))
+                       r = -EFAULT;
+               else
+                       r = omapfb_set_update_mode(fbdev, p.update_mode);
+               break;
+       case OMAPFB_GET_UPDATE_MODE:
+               p.update_mode = omapfb_get_update_mode(fbdev);
+               if (put_user(p.update_mode,
+                                       (enum omapfb_update_mode __user *)arg))
+                       r = -EFAULT;
+               break;
+       case OMAPFB_UPDATE_WINDOW:
+               if (copy_from_user(&p.update_window, (void __user *)arg,
+                                  sizeof(p.update_window)))
+                       r = -EFAULT;
+               else
+                       r = omapfb_update_win(fbdev, &p.update_window);
+               break;
+       case OMAPFB_SETUP_PLANE:
+               if (copy_from_user(&p.setup_plane, (void __user *)arg,
+                                  sizeof(p.setup_plane)))
+                       r = -EFAULT;
+               else
+                       r = omapfb_setup_plane(fbdev, &p.setup_plane);
+               break;
+       case OMAPFB_ENABLE_PLANE:
+               if (copy_from_user(&p.enable_plane, (void __user *)arg,
+                                  sizeof(p.enable_plane)))
+                       r = -EFAULT;
+               else
+                       r = omapfb_enable_plane(fbdev,
+                               p.enable_plane.plane, p.enable_plane.enable);
+               break;
+       case OMAPFB_SET_COLOR_KEY:
+               if (copy_from_user(&p.color_key, (void __user *)arg,
+                                  sizeof(p.color_key)))
+                       r = -EFAULT;
+               else
+                       r = omapfb_set_color_key(fbdev, &p.color_key);
+               break;
+       case OMAPFB_GET_CAPS:
+               p.caps = omapfb_get_caps(fbi);
+               if (put_user(p.caps, (unsigned long __user *)arg))
+                       r = -EFAULT;
+               break;
+       case OMAPFB_LCD_TEST:
+               {
+                       int test_num;
+
+                       if (get_user(test_num, (int __user *)arg)) {
+                               r = -EFAULT;
+                               break;
+                       }
+                       if (!fbdev->panel->run_test) {
+                               r = -EINVAL;
+                               break;
+                       }
+                       r = fbdev->panel->run_test(test_num);
+                       break;
+               }
+       case OMAPFB_CTRL_TEST:
+               {
+                       int test_num;
+
+                       if (get_user(test_num, (int __user *)arg)) {
+                               r = -EFAULT;
+                               break;
+                       }
+                       if (!fbdev->ctrl->run_test) {
+                               r = -EINVAL;
+                               break;
+                       }
+                       r = fbdev->ctrl->run_test(test_num);
+                       break;
+               }
+       default:
+               r = -EINVAL;
+       }
+
+       DBGLEAVE(2);
+       return r;
+}
+
+/* Callback table for the frame buffer framework. Some of these pointers
+ * will be changed according to the current setting of fb_info->accel_flags.
+ */
+static struct fb_ops omapfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_open        = omapfb_open,
+       .fb_release     = omapfb_release,
+       .fb_setcolreg   = omapfb_setcolreg,
+       .fb_setcmap     = omapfb_setcmap,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_blank       = omapfb_blank,
+       .fb_ioctl       = omapfb_ioctl,
+       .fb_check_var   = omapfb_check_var,
+       .fb_set_par     = omapfb_set_par,
+       .fb_rotate      = omapfb_rotate,
+       .fb_pan_display = omapfb_pan_display,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Sysfs interface
+ * ---------------------------------------------------------------------------
+ */
+/* omapfbX sysfs entries */
+static ssize_t omapfb_show_caps_num(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+       return snprintf(buf, PAGE_SIZE, "%#010lx\n",
+               omapfb_get_caps(fbdev->fb_info));
+}
+
+static ssize_t omapfb_show_caps_text(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       int pos = 0;
+       int i;
+       unsigned long caps;
+
+       caps = omapfb_get_caps(fbdev->fb_info);
+       for (i = 0; i < ARRAY_SIZE(omapfb_caps_table) && pos < PAGE_SIZE; i++) {
+               if (omapfb_caps_table[i].flag & caps) {
+                       pos += snprintf(&buf[pos], PAGE_SIZE - pos, "%s\n",
+                                       omapfb_caps_table[i].name);
+               }
+       }
+       return min((int)PAGE_SIZE, pos);
+}
+
+static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
+static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
+
+/* panel sysfs entries */
+static ssize_t omapfb_show_panel_name(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
+}
+
+static ssize_t omapfb_show_bklight_level(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       int r;
+
+       if (fbdev->panel->get_bklight_level) {
+               r = snprintf(buf, PAGE_SIZE, "%d\n",
+                            fbdev->panel->get_bklight_level());
+       } else
+               r = -ENODEV;
+       return r;
+}
+
+static ssize_t omapfb_store_bklight_level(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t size)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       int r;
+
+       if (fbdev->panel->set_bklight_level) {
+               unsigned int level;
+
+               if (sscanf(buf, "%10d", &level) == 1) {
+                       r = fbdev->panel->set_bklight_level(level);
+               } else
+                       r = -EINVAL;
+       } else
+               r = -ENODEV;
+       return r ? r : size;
+}
+
+static ssize_t omapfb_show_bklight_max(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       int r;
+
+       if (fbdev->panel->get_bklight_level) {
+               r = snprintf(buf, PAGE_SIZE, "%d\n",
+                            fbdev->panel->get_bklight_max());
+       } else
+               r = -ENODEV;
+       return r;
+}
+
+static struct device_attribute dev_attr_panel_name =
+       __ATTR(name, 0444, omapfb_show_panel_name, NULL);
+static DEVICE_ATTR(backlight_level, 0664,
+                  omapfb_show_bklight_level, omapfb_store_bklight_level);
+static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
+
+static struct attribute *panel_attrs[] = {
+       &dev_attr_panel_name.attr,
+       &dev_attr_backlight_level.attr,
+       &dev_attr_backlight_max.attr,
+       NULL,
+};
+
+static struct attribute_group panel_attr_grp = {
+       .name  = "panel",
+       .attrs = panel_attrs,
+};
+
+/* ctrl sysfs entries */
+static ssize_t omapfb_show_ctrl_name(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
+}
+
+static struct device_attribute dev_attr_ctrl_name =
+       __ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
+
+static struct attribute *ctrl_attrs[] = {
+       &dev_attr_ctrl_name.attr,
+       NULL,
+};
+
+static struct attribute_group ctrl_attr_grp = {
+       .name  = "ctrl",
+       .attrs = ctrl_attrs,
+};
+
+static int omapfb_register_sysfs(struct omapfb_device *fbdev)
+{
+       int r;
+
+       if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
+               goto fail0;
+
+       if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
+               goto fail1;
+
+       if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
+               goto fail2;
+
+       if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
+               goto fail3;
+
+       return 0;
+fail3:
+       sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+fail2:
+       device_remove_file(fbdev->dev, &dev_attr_caps_text);
+fail1:
+       device_remove_file(fbdev->dev, &dev_attr_caps_num);
+fail0:
+       pr_err("unable to register sysfs interface\n");
+       return r;
+}
+
+static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
+{
+       sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
+       sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
+       device_remove_file(fbdev->dev, &dev_attr_caps_num);
+       device_remove_file(fbdev->dev, &dev_attr_caps_text);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * LDM callbacks
+ * ---------------------------------------------------------------------------
+ */
+/* Initialize system fb_info object and set the default video mode.
+ * The frame buffer memory already allocated by lcddma_init
+ */
+static int fbinfo_init(struct omapfb_device *fbdev)
+{
+       struct fb_info                  *info = fbdev->fb_info;
+       struct fb_var_screeninfo        *var = &info->var;
+       int                             r = 0;
+
+       DBGENTER(1);
+
+       BUG_ON(!fbdev->vram_virt_base);
+
+       info->fbops = &omapfb_ops;
+       info->flags = FBINFO_FLAG_DEFAULT;
+       info->screen_base = (char __iomem *)fbdev->vram_virt_base;
+
+       info->pseudo_palette = fbdev->pseudo_palette;
+
+       var->accel_flags  = def_accel ? FB_ACCELF_TEXT : 0;
+       var->xres_virtual = def_vxres;
+       var->yres_virtual = def_vyres;
+       var->rotate       = def_rotate;
+
+       fbdev->mirror = def_mirror;
+
+       set_fb_var(fbdev, var);
+       set_fb_fix(fbdev);
+
+       r = fb_alloc_cmap(&info->cmap, 16, 0);
+       if (r != 0)
+               pr_err("unable to allocate color map memory\n");
+
+       DBGLEAVE(1);
+       return r;
+}
+
+/* Release the fb_info object */
+static void fbinfo_cleanup(struct omapfb_device *fbdev)
+{
+       DBGENTER(1);
+
+       fb_dealloc_cmap(&fbdev->fb_info->cmap);
+
+       DBGLEAVE(1);
+}
+
+/* Free driver resources. Can be called to rollback an aborted initialization
+ * sequence.
+ */
+static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
+{
+       switch (state) {
+       case OMAPFB_ACTIVE:
+               unregister_framebuffer(fbdev->fb_info);
+       case 6:
+               omapfb_unregister_sysfs(fbdev);
+               omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+       case 5:
+               fbdev->panel->disable();
+       case 4:
+               fbinfo_cleanup(fbdev);
+       case 3:
+               ctrl_cleanup(fbdev);
+       case 2:
+               fbdev->panel->cleanup();
+       case 1:
+               dev_set_drvdata(fbdev->dev, NULL);
+               framebuffer_release(fbdev->fb_info);
+       case 0:
+               /* nothing to free */
+               break;
+       default:
+               BUG();
+       }
+}
+
+static int omapfb_find_panel(struct omapfb_device *fbdev)
+{
+       const struct omap_lcd_config *conf;
+       char name[17];
+       int i;
+
+       conf = (struct omap_lcd_config *)fbdev->dev->platform_data;
+       fbdev->panel = NULL;
+       if (conf == NULL)
+               return -1;
+
+       strncpy(name, conf->panel_name, sizeof(name) - 1);
+       name[sizeof(name) - 1] = 0;
+       for (i = 0; i < ARRAY_SIZE(panels); i++) {
+               if (strcmp(panels[i]->name, name) == 0) {
+                       fbdev->panel = panels[i];
+                       break;
+               }
+       }
+
+       if (fbdev->panel == NULL)
+               return -1;
+
+       return 0;
+}
+
+static int omapfb_find_ctrl(struct omapfb_device *fbdev)
+{
+       struct omap_lcd_config *conf;
+       char name[17];
+       int i;
+
+       conf = (struct omap_lcd_config *)fbdev->dev->platform_data;
+
+       fbdev->ctrl = NULL;
+       if (conf == NULL)
+               return -1;
+
+       strncpy(name, conf->ctrl_name, sizeof(name) - 1);
+       name[sizeof(name) - 1] = '\0';
+
+       if (strcmp(name, "internal") == 0) {
+               fbdev->ctrl = fbdev->int_ctrl;
+               return 0;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
+               if (strcmp(ctrls[i]->name, name) == 0) {
+                       fbdev->ctrl = ctrls[i];
+                       break;
+               }
+       }
+
+       if (fbdev->ctrl == NULL)
+               return -1;
+
+       return 0;
+}
+
+static void check_required_callbacks(struct omapfb_device *fbdev)
+{
+#define _C(x) (fbdev->ctrl->x != NULL)
+#define _P(x) (fbdev->panel->x != NULL)
+       BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL);
+       BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
+                _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) &&
+                _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
+                _P(get_caps)));
+#undef _P
+#undef _C
+}
+
+/* Called by LDM binding to probe and attach a new device.
+ * Initialization sequence:
+ *   1. allocate system fb_info structure
+ *      select panel type according to machine type
+ *   2. init LCD panel
+ *   3. init LCD controller and LCD DMA
+ *   4. init system fb_info structure
+ *   5. init gfx DMA
+ *   6. enable LCD panel
+ *      start LCD frame transfer
+ *   7. register system fb_info structure
+ */
+static int omapfb_probe(struct device *dev)
+{
+       struct platform_device  *pdev;
+       struct omapfb_device    *fbdev = NULL;
+       struct fb_info          *fbi;
+       int                     init_state;
+       unsigned long           phz, hhz, vhz;
+       struct lcd_panel        *panel;
+       int                     r = 0;
+
+       DBGENTER(1);
+
+       init_state = 0;
+
+       pdev = to_platform_device(dev);
+       if (pdev->num_resources != 0) {
+               pr_err("probed for an unknown device\n");
+               r = -ENODEV;
+               goto cleanup;
+       }
+
+       fbi = framebuffer_alloc(sizeof(struct omapfb_device), dev);
+       if (fbi == NULL) {
+               pr_err("unable to allocate memory for device info\n");
+               r = -ENOMEM;
+               goto cleanup;
+       }
+       init_state++;
+
+       fbdev = (struct omapfb_device *)fbi->par;
+       fbdev->fb_info = fbi;
+       fbdev->dev = dev;
+       dev_set_drvdata(dev, fbdev);
+
+       init_MUTEX(&fbdev->rqueue_sema);
+
+#ifdef CONFIG_ARCH_OMAP1
+       fbdev->int_ctrl = &omap1_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+       fbdev->ext_if = &sossi_extif;
+#endif
+#else  /* OMAP2 */
+       fbdev->int_ctrl = &omap2_int_ctrl;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+       fbdev->ext_if = &rfbi_extif;
+#endif
+#endif
+       if (omapfb_find_ctrl(fbdev) < 0) {
+               pr_err("LCD controller not found, board not supported\n");
+               r = -ENODEV;
+               goto cleanup;
+       }
+
+       if (omapfb_find_panel(fbdev) < 0) {
+               pr_err("LCD panel not found, board not supported\n");
+               r = -ENODEV;
+               goto cleanup;
+       }
+
+       check_required_callbacks(fbdev);
+
+
+       pr_info(MODULE_NAME ": configured for panel %s\n", fbdev->panel->name);
+
+       r = fbdev->panel->init(fbdev);
+       if (r)
+               goto cleanup;
+       init_state++;
+
+       r = ctrl_init(fbdev);
+       if (r)
+               goto cleanup;
+       init_state++;
+
+       r = fbinfo_init(fbdev);
+       if (r)
+               goto cleanup;
+       init_state++;
+
+#ifdef CONFIG_FB_OMAP_DMA_TUNE
+       /* Set DMA priority for EMIFF access to highest */
+       omap_set_dma_priority(OMAP_DMA_PORT_EMIFF, 15);
+#endif
+
+       r = fbdev->panel->enable();
+       if (r)
+               goto cleanup;
+       init_state++;
+
+       r = ctrl_change_mode(fbdev);
+       if (r) {
+               pr_err("mode setting failed\n");
+               goto cleanup;
+       }
+
+       omapfb_enable_plane(fbdev, 0, 1);
+
+       omapfb_set_update_mode(fbdev, manual_update ?
+                                  OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
+
+       r = omapfb_register_sysfs(fbdev);
+       if (r)
+               goto cleanup;
+       init_state++;
+
+       r = register_framebuffer(fbdev->fb_info);
+       if (r != 0) {
+               pr_err("register_framebuffer failed\n");
+               goto cleanup;
+       }
+
+       fbdev->state = OMAPFB_ACTIVE;
+
+       panel = fbdev->panel;
+       phz = panel->pixel_clock * 1000;
+       hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
+       vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
+
+       pr_info(MODULE_NAME ": initialized vram=%lu "
+                       "pixclock %lu kHz hfreq %lu.%lu kHz vfreq %lu.%lu Hz\n",
+                       fbdev->vram_size,
+                       phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
+
+       DBGLEAVE(1);
+       return 0;
+
+cleanup:
+       omapfb_free_resources(fbdev, init_state);
+
+       DBGLEAVE(1);
+       return r;
+}
+
+/* Called when the device is being detached from the driver */
+static int omapfb_remove(struct device *dev)
+{
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
+       enum omapfb_state saved_state = fbdev->state;
+
+       DBGENTER(1);
+       /* FIXME: wait till completion of pending events */
+
+       fbdev->state = OMAPFB_DISABLED;
+       omapfb_free_resources(fbdev, saved_state);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+/* PM suspend */
+static int omapfb_suspend(struct device *dev, pm_message_t mesg)
+{
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
+
+       DBGENTER(1);
+
+       omapfb_blank(VESA_POWERDOWN, fbdev->fb_info);
+
+       DBGLEAVE(1);
+
+       return 0;
+}
+
+/* PM resume */
+static int omapfb_resume(struct device *dev)
+{
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
+
+       DBGENTER(1);
+
+       omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info);
+
+       DBGLEAVE(1);
+       return 0;
+}
+
+static struct device_driver omapfb_driver = {
+       .name           = OMAPFB_DRIVER,
+       .bus            = &platform_bus_type,
+       .probe          = omapfb_probe,
+       .remove         = omapfb_remove,
+       .suspend        = omapfb_suspend,
+       .resume         = omapfb_resume
+};
+
+#ifndef MODULE
+
+/* Process kernel command line parameters */
+static int __init omapfb_setup(char *options)
+{
+       char *this_opt = NULL;
+       int r = 0;
+
+       DBGENTER(1);
+
+       if (!options || !*options)
+               goto exit;
+
+       while (!r && (this_opt = strsep(&options, ",")) != NULL) {
+               if (!strncmp(this_opt, "accel", 5))
+                       def_accel = 1;
+               else if (!strncmp(this_opt, "vram:", 5)) {
+                       char *suffix;
+                       def_vram = (simple_strtoul(this_opt + 5, &suffix, 0));
+                       switch (suffix[0]) {
+                       case '\0':
+                               break;
+                       case 'm':
+                       case 'M':
+                               def_vram *= 1024;
+                               /* Fall through */
+                       case 'k':
+                       case 'K':
+                               def_vram *= 1024;
+                               break;
+                       default:
+                               pr_err("invalid vram suffix\n");
+                               r = -1;
+                       }
+               }
+               else if (!strncmp(this_opt, "vxres:", 6))
+                       def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
+               else if (!strncmp(this_opt, "vyres:", 6))
+                       def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
+               else if (!strncmp(this_opt, "rotate:", 7))
+                       def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
+               else if (!strncmp(this_opt, "mirror:", 7))
+                       def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
+               else if (!strncmp(this_opt, "manual_update", 13))
+                       manual_update = 1;
+               else {
+                       pr_err("invalid option\n");
+                       r = -1;
+               }
+       }
+exit:
+       DBGLEAVE(1);
+       return r;
+}
+
+#endif
+
+/* Register both the driver and the device */
+static int __init omapfb_init(void)
+{
+       int r = 0;
+
+       DBGENTER(1);
+
+#ifndef MODULE
+       {
+               char *option;
+
+               if (fb_get_options("omapfb", &option)) {
+                       r = -ENODEV;
+                       goto exit;
+               }
+               omapfb_setup(option);
+       }
+#endif
+       /* Register the driver with LDM */
+       if (driver_register(&omapfb_driver)) {
+               pr_err("failed to register omapfb driver\n");
+               r = -ENODEV;
+               goto exit;
+       }
+
+exit:
+       DBGLEAVE(1);
+       return r;
+}
+
+static void __exit omapfb_cleanup(void)
+{
+       DBGENTER(1);
+
+       driver_unregister(&omapfb_driver);
+
+       DBGLEAVE(1);
+}
+
+module_param_named(accel, def_accel, uint, 0664);
+module_param_named(vram, def_vram, ulong, 0664);
+module_param_named(vxres, def_vxres, long, 0664);
+module_param_named(vyres, def_vyres, long, 0664);
+module_param_named(rotate, def_rotate, uint, 0664);
+module_param_named(mirror, def_mirror, uint, 0664);
+module_param_named(manual_update, manual_update, bool, 0664);
+
+module_init(omapfb_init);
+module_exit(omapfb_cleanup);
+
+MODULE_DESCRIPTION("TI OMAP framebuffer driver");
+MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
new file mode 100644 (file)
index 0000000..a288b46
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * File: drivers/video/omap/omap2/rfbi.c
+ *
+ * OMAP2 Remote Frame Buffer Interface support
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ *        Imre Deak <imre.deak@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/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+#include <asm/arch/omapfb.h>
+
+#include "dispc.h"
+
+#define MODULE_NAME "omapfb-rfbi"
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+#define RFBI_BASE              0x48050800
+#define RFBI_REVISION          0x0000
+#define RFBI_SYSCONFIG         0x0010
+#define RFBI_SYSSTATUS         0x0014
+#define RFBI_CONTROL           0x0040
+#define RFBI_PIXEL_CNT         0x0044
+#define RFBI_LINE_NUMBER       0x0048
+#define RFBI_CMD               0x004c
+#define RFBI_PARAM             0x0050
+#define RFBI_DATA              0x0054
+#define RFBI_READ              0x0058
+#define RFBI_STATUS            0x005c
+#define RFBI_CONFIG0           0x0060
+#define RFBI_ONOFF_TIME0       0x0064
+#define RFBI_CYCLE_TIME0       0x0068
+#define RFBI_DATA_CYCLE1_0     0x006c
+#define RFBI_DATA_CYCLE2_0     0x0070
+#define RFBI_DATA_CYCLE3_0     0x0074
+#define RFBI_VSYNC_WIDTH       0x0090
+#define RFBI_HSYNC_WIDTH       0x0094
+
+#define DISPC_BASE             0x48050400
+#define DISPC_CONTROL          0x0040
+
+static struct {
+       u32             base;
+       void            (*lcdc_callback)(void *data);
+       void            *lcdc_callback_data;
+       unsigned long   l4_khz;
+} rfbi;
+
+static inline void rfbi_write_reg(int idx, u32 val)
+{
+       __raw_writel(val, rfbi.base + idx);
+}
+
+static inline u32 rfbi_read_reg(int idx)
+{
+       return __raw_readl(rfbi.base + idx);
+}
+
+static int ns_to_l4_ticks(int time)
+{
+       unsigned long tick_ps;
+       int ret;
+
+       /* Calculate in picosecs to yield more exact results */
+       tick_ps = 1000000000 / (rfbi.l4_khz);
+
+       ret = (time * 1000 + tick_ps - 1) / tick_ps;
+
+       return ret * 2;
+}
+
+#ifdef OMAPFB_DBG
+static void print_timings(void)
+{
+       u32 l;
+
+       DBGPRINT(1, "Tick time %lu ps\n", 1000000000 / rfbi.l4_khz);
+       l = rfbi_read_reg(RFBI_ONOFF_TIME0);
+       DBGPRINT(1, "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
+              "REONTIME %d, REOFFTIME %d\n",
+              l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
+              (l >> 20) & 0x0f, (l >> 24) & 0x3f);
+       l = rfbi_read_reg(RFBI_CYCLE_TIME0);
+       DBGPRINT(1, "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
+              "ACCESSTIME %d\n",
+              (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, (l >> 22) & 0x3f);
+}
+#endif
+
+static void rfbi_set_timings(const struct extif_timings *t)
+{
+       u32 l;
+       int on, off;
+
+       on = ns_to_l4_ticks(t->cs_on_time) & 0x0f;
+       l = on;
+       off = ns_to_l4_ticks(t->cs_off_time) & 0x3f;
+       if (off <= on)
+               off = on + 2;
+       l |= off << 4;
+
+       on = ns_to_l4_ticks(t->we_on_time) & 0x0f;
+       l |= on << 10;
+       off = ns_to_l4_ticks(t->we_off_time) & 0x3f;
+       if (off <= on)
+               off = on + 2;
+       l |= off << 14;
+
+       l |= (ns_to_l4_ticks(t->re_on_time) & 0x0f) << 20;
+       l |= (ns_to_l4_ticks(t->re_off_time) & 0x3f) << 24;
+       rfbi_write_reg(RFBI_ONOFF_TIME0, l);
+
+       l = ns_to_l4_ticks(t->we_cycle_time) & 0x3f;
+       l |= (ns_to_l4_ticks(t->re_cycle_time) & 0x3f) << 6;
+       l |= (ns_to_l4_ticks(t->cs_pulse_width) & 0x3f) << 12;
+       l |= (ns_to_l4_ticks(t->access_time) & 0x3f) << 22;
+       rfbi_write_reg(RFBI_CYCLE_TIME0, l);
+}
+
+static void rfbi_write_command(u32 cmd)
+{
+       rfbi_write_reg(RFBI_CMD, cmd);
+}
+
+static u32 rfbi_read_data(void)
+{
+       u32 val;
+
+       rfbi_write_reg(RFBI_READ, 0);
+       val = rfbi_read_reg(RFBI_READ);
+       return val;
+}
+
+static void rfbi_write_data(u32 val)
+{
+       rfbi_write_reg(RFBI_PARAM, val);
+}
+
+static void rfbi_transfer_area(int width, int height,
+                               void (callback)(void * data), void *data)
+{
+       u32 w;
+
+       BUG_ON(callback == NULL);
+
+       omap_dispc_set_lcd_size(width, height);
+
+       rfbi.lcdc_callback = callback;
+       rfbi.lcdc_callback_data = data;
+
+       rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
+
+       w = rfbi_read_reg(RFBI_CONTROL);
+       /* Enable, Internal trigger */
+       rfbi_write_reg(RFBI_CONTROL, w | (1 << 0) | (1 << 4));
+
+       omap_dispc_enable_lcd_out(1);
+}
+
+static inline void _stop_transfer(void)
+{
+       u32 w;
+
+       w = rfbi_read_reg(RFBI_CONTROL);
+       rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
+}
+
+static void rfbi_dma_callback(void *data)
+{
+       _stop_transfer();
+       rfbi.lcdc_callback(rfbi.lcdc_callback_data);
+}
+
+static int rfbi_init(void)
+{
+       u32 l;
+       int r;
+       struct clk *dss_ick;
+
+       memset(&rfbi, 0, sizeof(rfbi));
+       rfbi.base = io_p2v(RFBI_BASE);
+
+       l = rfbi_read_reg(RFBI_REVISION);
+       pr_info(MODULE_NAME ": version %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
+
+       dss_ick = clk_get(NULL, "dss_ick");
+       if (IS_ERR(dss_ick)) {
+               pr_err("can't get dss_ick\n");
+               return PTR_ERR(dss_ick);
+       }
+       rfbi.l4_khz = clk_get_rate(dss_ick) / 1000;
+       clk_put(dss_ick);
+
+       /* Reset */
+       rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
+       while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
+
+       l = rfbi_read_reg(RFBI_SYSCONFIG);
+       /* Enable autoidle and smart-idle */
+       l |= (1 << 0) | (2 << 3);
+       rfbi_write_reg(RFBI_SYSCONFIG, l);
+
+       /* 16-bit interface, ITE trigger mode, 16-bit data */
+       l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
+       l |= (0 << 9) | (1 << 20) | (1 << 21);
+       rfbi_write_reg(RFBI_CONFIG0, l);
+
+       l = 0x10;
+       rfbi_write_reg(RFBI_DATA_CYCLE1_0, l);
+       rfbi_write_reg(RFBI_DATA_CYCLE2_0, l);
+       rfbi_write_reg(RFBI_DATA_CYCLE3_0, l);
+
+       l = rfbi_read_reg(RFBI_CONTROL);
+       /* Select CS0 */
+       l = (0x01 << 2);
+       rfbi_write_reg(RFBI_CONTROL, l);
+
+       if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) {
+               pr_err("can't get DISPC irq\n");
+               return r;
+       }
+
+       return 0;
+}
+
+static void rfbi_cleanup(void)
+{
+       omap_dispc_free_irq();
+}
+
+struct lcd_ctrl_extif rfbi_extif = {
+       .init                   = rfbi_init,
+       .cleanup                = rfbi_cleanup,
+       .set_timings            = rfbi_set_timings,
+       .write_command          = rfbi_write_command,
+       .read_data              = rfbi_read_data,
+       .write_data             = rfbi_write_data,
+       .transfer_area          = rfbi_transfer_area,
+};
+
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
new file mode 100644 (file)
index 0000000..e2145eb
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * File: drivers/video/omap/omap1/sossi.c
+ *
+ * OMAP1 Special OptimiSed Screen Interface support
+ *
+ * Copyright (C) 2004-2005 Nokia Corporation
+ * Author: 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 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/mm.h>
+#include <asm/hardware/clock.h>
+#include <asm/io.h>
+
+#include "sossi.h"
+
+#define MODULE_NAME            "omapfb-sossi"
+
+#define OMAP_SOSSI_BASE         0xfffbac00
+#define SOSSI_ID_REG           0x00
+#define SOSSI_INIT1_REG                0x04
+#define SOSSI_INIT2_REG                0x08
+#define SOSSI_INIT3_REG                0x0c
+#define SOSSI_FIFO_REG         0x10
+#define SOSSI_REOTABLE_REG     0x14
+#define SOSSI_TEARING_REG      0x18
+#define SOSSI_INIT1B_REG       0x1c
+#define SOSSI_FIFOB_REG                0x20
+
+#define DMA_GSCR          0xfffedc04
+#define DMA_LCD_CCR       0xfffee3c2
+#define DMA_LCD_CTRL      0xfffee3c4
+#define DMA_LCD_LCH_CTRL  0xfffee3ea
+
+#define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
+
+static int sossi_base = IO_ADDRESS(OMAP_SOSSI_BASE);
+
+static inline u32 sossi_read_reg(int reg)
+{
+        return readl(sossi_base + reg);
+}
+
+static inline u16 sossi_read_reg16(int reg)
+{
+        return readw(sossi_base + reg);
+}
+
+static inline u8 sossi_read_reg8(int reg)
+{
+        return readb(sossi_base + reg);
+}
+
+static inline void sossi_write_reg(int reg, u32 value)
+{
+        writel(value, sossi_base + reg);
+}
+
+static inline void sossi_write_reg16(int reg, u16 value)
+{
+        writew(value, sossi_base + reg);
+}
+
+static inline void sossi_write_reg8(int reg, u8 value)
+{
+        writeb(value, sossi_base + reg);
+}
+
+static void sossi_set_bits(int reg, u32 bits)
+{
+        sossi_write_reg(reg, sossi_read_reg(reg) | bits);
+}
+
+static void sossi_clear_bits(int reg, u32 bits)
+{
+        sossi_write_reg(reg, sossi_read_reg(reg) & ~bits);
+}
+
+#define MOD_CONF_CTRL_1   0xfffe1110
+#define CONF_SOSSI_RESET_R      (1 << 23)
+#define CONF_MOD_SOSSI_CLK_EN_R (1 << 16)
+
+static struct clk *dpll_clk;
+
+int sossi_init(void)
+{
+       u32 l, k;
+
+       dpll_clk = clk_get(NULL, "ck_dpll1");
+       BUG_ON(dpll_clk == NULL);
+
+       /* Reset and enable the SoSSI module */
+       l = omap_readl(MOD_CONF_CTRL_1);
+       l |= CONF_SOSSI_RESET_R;
+       omap_writel(l, MOD_CONF_CTRL_1);
+       l &= ~CONF_SOSSI_RESET_R;
+       omap_writel(l, MOD_CONF_CTRL_1);
+
+       l |= CONF_MOD_SOSSI_CLK_EN_R;
+       omap_writel(l, MOD_CONF_CTRL_1);
+
+       omap_writel(omap_readl(ARM_IDLECT2) | (1 << 11), ARM_IDLECT2);
+       omap_writel(omap_readl(ARM_IDLECT1) | (1 << 6), ARM_IDLECT1);
+
+       l = sossi_read_reg(SOSSI_INIT2_REG);
+       /* Enable and reset the SoSSI block */
+       l |= (1 << 0) | (1 << 1);
+       sossi_write_reg(SOSSI_INIT2_REG, l);
+       /* Take SoSSI out of reset */
+       l &= ~(1 << 1);
+       sossi_write_reg(SOSSI_INIT2_REG, l);
+
+       sossi_write_reg(SOSSI_ID_REG, 0);
+       l = sossi_read_reg(SOSSI_ID_REG);
+       k = sossi_read_reg(SOSSI_ID_REG);
+
+       if (l != 0x55555555 || k != 0xaaaaaaaa) {
+               pr_err("Invalid SoSSI sync pattern: %08x, %08x\n", l, k);
+               return -ENODEV;
+       }
+       l = sossi_read_reg(SOSSI_ID_REG); /* Component code */
+       l = sossi_read_reg(SOSSI_ID_REG);
+       pr_info(KERN_INFO MODULE_NAME ": version %d.%d initialized\n",
+                       l >> 16, l & 0xffff);
+
+       l = sossi_read_reg(SOSSI_INIT1_REG);
+       l |= (1 << 19); /* DMA_MODE */
+       l &= ~(1 << 31); /* REORDERING */
+       sossi_write_reg(SOSSI_INIT1_REG, l);
+
+       return 0;
+}
+
+static unsigned long get_sossi_clk_rate(int div)
+{
+       return (clk_get_rate(dpll_clk)) / div;
+}
+
+static unsigned long get_sossi_clk_period(int div)
+{
+       /* In picoseconds */
+       return 1000000000 / (get_sossi_clk_rate(div) / 1000);
+}
+
+static int ns_to_sossi_ticks(int time, int div)
+{
+       unsigned long tick_ps;
+
+       /* Calculate in picosecs to yield more exact results */
+       tick_ps = get_sossi_clk_period(div);
+
+       return (time * 1000 + tick_ps - 1) / tick_ps;
+}
+
+static int set_timings(int div, int tw0, int tw1)
+{
+       u32 l;
+
+       if (tw1 * 1000 > 64 * get_sossi_clk_period(div))
+               return -1;
+       if (tw0 * 1000 > 16 * get_sossi_clk_period(div))
+               return -1;
+
+       l = omap_readl(MOD_CONF_CTRL_1);
+       l &= ~(7 << 17);
+       l |= (div - 1) << 17;
+       omap_writel(l, MOD_CONF_CTRL_1);
+
+       tw0 = ns_to_sossi_ticks(tw0, div) - 1;
+       tw1 = ns_to_sossi_ticks(tw1, div) - 1;
+       if (tw0 < 0)
+               tw0 = 0;
+       if (tw1 < 0)
+               tw1 = 0;
+#if 0
+       printk("Using TW0 = %d, TW1 = %d, div = %d, period = %d ps\n",
+              tw0, tw1, div, get_sossi_clk_period(div));
+#endif
+       l = sossi_read_reg(SOSSI_INIT1_REG);
+       l &= ~((0x0f << 20) | (0x3f << 24));
+       l |= ((tw0 & 0x0f) << 20) | ((tw1 & 0x3f) << 24);
+       sossi_write_reg(SOSSI_INIT1_REG, l);
+
+       return 0;
+}
+
+static struct sossi {
+       int bus_pick_width;
+} sossi;
+
+void sossi_set_timings(int min_time, int min_tw0, int min_tw1)
+{
+       int div;
+
+       for (div = 1; div <= 8; div++) {
+               if (min_time * 1000 > get_sossi_clk_period(div))
+                       continue;
+               if (set_timings(div, min_tw0, min_tw1) == 0)
+                       break;
+       }
+       if (div == 9) {
+               pr_err("DPLL frequency too high for SoSSI\n");
+               BUG();
+       }
+}
+
+void sossi_set_xfer_params(int bus_pick_count, int bus_pick_width)
+{
+       u32 l;
+
+       sossi.bus_pick_width = bus_pick_width;
+       l = ((bus_pick_count - 1) << 5) | ((bus_pick_width - 1) & 0x1f);
+       sossi_write_reg(SOSSI_INIT3_REG, l);
+}
+
+void sossi_start_transfer(void)
+{
+       /* WE */
+       sossi_clear_bits(SOSSI_INIT2_REG, 1 << 4);
+       /* CS active low */
+       sossi_clear_bits(SOSSI_INIT1_REG, 1 << 30);
+       /* FIXME: locking? */
+}
+
+void sossi_stop_transfer(void)
+{
+       /* WE */
+       sossi_set_bits(SOSSI_INIT2_REG, 1 << 4);
+       /* CS active low */
+       sossi_set_bits(SOSSI_INIT1_REG, 1 << 30);
+       /* FIXME: locking? */
+}
+
+static void send_data(const void *data, unsigned int len)
+{
+       while (len >= 4) {
+               sossi_write_reg(SOSSI_FIFO_REG, *(const u32 *) data);
+               len -= 4;
+               data += 4;
+       }
+       while (len >= 2) {
+               sossi_write_reg16(SOSSI_FIFO_REG, *(const u16 *) data);
+               len -= 2;
+               data += 2;
+       }
+       while (len) {
+               sossi_write_reg8(SOSSI_FIFO_REG, *(const u8 *) data);
+               len--;
+               data++;
+       }
+}
+
+static void set_cycles(unsigned int len)
+{
+       int nr_cycles = len / (sossi.bus_pick_width / 8);
+
+       sossi_clear_bits(SOSSI_INIT1_REG, 0x3ffff);
+       sossi_set_bits(SOSSI_INIT1_REG, (nr_cycles - 1) & 0x3ffff);
+}
+
+void sossi_send_cmd(const void *data, unsigned int len)
+{
+       sossi_clear_bits(SOSSI_INIT1_REG, 1 << 18);
+       set_cycles(len);
+       send_data(data, len);
+}
+
+void sossi_send_data(const void *data, unsigned int len)
+{
+       sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+       set_cycles(len);
+       send_data(data, len);
+}
+
+void sossi_prepare_dma_transfer(unsigned int count)
+{
+       sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+       set_cycles(count);
+}
+
+void sossi_send_data_const32(u32 data, unsigned int count)
+{
+       sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+       set_cycles(count * 4);
+       while (count > 0) {
+               sossi_write_reg(SOSSI_FIFO_REG, data);
+               count--;
+       }
+}
+
+void sossi_set_tearing(int mode, int hs_counter, int detect_limit,
+                      int vs_counter, int vs_detect_limit, int flags)
+{
+       u32 l = 0;
+
+       l |= vs_counter << 30;
+       if (flags & SOSSI_FLAG_HS_INVERTED)
+               l |= 1 << 29;
+       if (flags & SOSSI_FLAG_VS_INVERTED)
+               l |= 1 << 28;
+       l |= mode << 26;
+       l |= hs_counter << 15;
+       l |= vs_detect_limit << 3;
+       l |= detect_limit;
+       sossi_write_reg(SOSSI_TEARING_REG, l);
+}
+
+void sossi_read_data(void *data, unsigned int len)
+{
+       /* Before reading we must check if some writings are going on */
+       while (!(sossi_read_reg(SOSSI_INIT2_REG) & (1 << 3)));
+       sossi_set_bits(SOSSI_INIT1_REG, 1 << 18);
+       set_cycles(len);
+       while (len >= 4) {
+               *(u32 *) data = sossi_read_reg(SOSSI_FIFO_REG);
+               len -= 4;
+               data += 4;
+       }
+       while (len >= 2) {
+               *(u16 *) data = sossi_read_reg16(SOSSI_FIFO_REG);
+               len -= 2;
+               data += 2;
+       }
+       while (len) {
+               *(u8 *) data = sossi_read_reg8(SOSSI_FIFO_REG);
+               len--;
+               data++;
+       }
+}
diff --git a/drivers/video/omap/sossi.h b/drivers/video/omap/sossi.h
new file mode 100644 (file)
index 0000000..b71a4b9
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef DRIVERS_VIDEO_OMAP_SOSSI_H
+#define DRIVERS_VIDEO_OMAP_SOSSI_H
+
+#define SOSSI_FLAG_HS_INVERTED          0x01
+#define SOSSI_FLAG_VS_INVERTED          0x02
+
+extern int sossi_init(void);
+extern void sossi_set_xfer_params(int bus_pick_count, int bus_pick_width);
+extern void sossi_set_timings(int tick_ns, int tw0_ns, int tw1_ns);
+extern void sossi_start_transfer(void);
+extern void sossi_stop_transfer(void);
+extern void sossi_send_cmd(const void *data, unsigned int len);
+extern void sossi_send_data(const void *data, unsigned int len);
+extern void sossi_send_data_const32(u32 data, unsigned int count);
+extern void sossi_prepare_dma_transfer(unsigned int count);
+extern void sossi_read_data(void *data, unsigned int len);
+extern void sossi_set_tearing(int mode, int hs_counter, int detect_limit,
+                             int vs_counter, int vs_detect_limit, int flags);
+
+#endif
diff --git a/include/asm-arm/.gitignore b/include/asm-arm/.gitignore
new file mode 100644 (file)
index 0000000..e1bf470
--- /dev/null
@@ -0,0 +1,3 @@
+arch
+asm-offsets.h
+mach-types.h
index d64ee9211eeddc63fbb888421f01157f72f382a1..0c54a96a823d1af26427dec597ede8fa0f56615b 100644 (file)
@@ -34,5 +34,7 @@
 #define OMAP24XX_ETHR_START             0x08000300
 #define OMAP24XX_ETHR_GPIO_IRQ         92
 
+#define H4_CS0_BASE                 0x04000000
+
 #endif /*  __ASM_ARCH_OMAP_H4_H */
 
index 79574e0ed13d3c82d03c13cd4fbcc7df69d5f4c2..b3cf33441f6e6915e991d6fa9e1cad314343d8b2 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef __ASM_ARCH_OMAP_INNOVATOR_H
 #define __ASM_ARCH_OMAP_INNOVATOR_H
 
-#if defined (CONFIG_ARCH_OMAP1510)
+#if defined (CONFIG_ARCH_OMAP15XX)
 
 #ifndef OMAP_SDRAM_DEVICE
 #define OMAP_SDRAM_DEVICE                      D256M_1X16_4B
@@ -44,7 +44,7 @@ void fpga_write(unsigned char val, int reg);
 unsigned char fpga_read(int reg);
 #endif
 
-#endif /* CONFIG_ARCH_OMAP1510 */
+#endif /* CONFIG_ARCH_OMAP15XX */
 
 #if defined (CONFIG_ARCH_OMAP16XX)
 
diff --git a/include/asm-arm/arch-omap/camera.h b/include/asm-arm/arch-omap/camera.h
new file mode 100644 (file)
index 0000000..8a68945
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * OMAP-1510 camera interface
+ *
+ * FIXME: This will go to same directory with the camera driver
+ */
+#define CAMERA_BASE            0xfffb6800
+#define CAM_CTRLCLOCK_REG      (CAMERA_BASE + 0x00)
+#define CAM_IT_STATUS_REG      (CAMERA_BASE + 0x04)
+#define CAM_MODE_REG           (CAMERA_BASE + 0x08)
+#define CAM_STATUS_REG         (CAMERA_BASE + 0x0C)
+#define CAM_CAMDATA_REG                (CAMERA_BASE + 0x10)
+#define CAM_GPIO_REG           (CAMERA_BASE + 0x14)
+#define CAM_PEAK_CTR_REG       (CAMERA_BASE + 0x18)
+
+#ifndef __ASSEMBLY__
+typedef struct {
+       __u32 ctrlclock;        /* 00 */
+       __u32 it_status;        /* 04 */
+       __u32 mode;             /* 08 */
+       __u32 status;           /* 0C */
+       __u32 camdata;          /* 10 */
+       __u32 gpio;             /* 14 */
+       __u32 peak_counter;     /* 18 */
+} camera_regs_t;
+#endif
+
+/* CTRLCLOCK bit shifts */
+#define FOSCMOD_BIT            0
+#define FOSCMOD_MASK           (0x7 << FOSCMOD_BIT)
+#define          FOSCMOD_12MHz         0x0
+#define          FOSCMOD_6MHz          0x2
+#define          FOSCMOD_9_6MHz        0x4
+#define          FOSCMOD_24MHz         0x5
+#define          FOSCMOD_8MHz          0x6
+#define POLCLK                 (1<<3)
+#define CAMEXCLK_EN            (1<<4)
+#define MCLK_EN                        (1<<5)
+#define DPLL_EN                        (1<<6)
+#define LCLK_EN                        (1<<7)
+
+/* IT_STATUS bit shifts */
+#define V_UP                   (1<<0)
+#define V_DOWN                 (1<<1)
+#define H_UP                   (1<<2)
+#define H_DOWN                 (1<<3)
+#define FIFO_FULL              (1<<4)
+#define DATA_XFER              (1<<5)
+
+/* MODE bit shifts */
+#define CAMOSC                 (1<<0)
+#define IMGSIZE_BIT            1
+#define IMGSIZE_MASK           (0x3 << IMGSIZE_BIT)
+#define          IMGSIZE_CIF           (0x0 << IMGSIZE_BIT)       /* 352x288 */
+#define          IMGSIZE_QCIF          (0x1 << IMGSIZE_BIT)       /* 176x144 */
+#define          IMGSIZE_VGA           (0x2 << IMGSIZE_BIT)       /* 640x480 */
+#define          IMGSIZE_QVGA          (0x3 << IMGSIZE_BIT)       /* 320x240 */
+#define ORDERCAMD              (1<<3)
+#define EN_V_UP                        (1<<4)
+#define EN_V_DOWN              (1<<5)
+#define EN_H_UP                        (1<<6)
+#define EN_H_DOWN              (1<<7)
+#define EN_DMA                 (1<<8)
+#define THRESHOLD              (1<<9)
+#define THRESHOLD_BIT          9
+#define THRESHOLD_MASK         (0x7f<<9)
+#define EN_NIRQ                        (1<<16)
+#define EN_FIFO_FULL           (1<<17)
+#define RAZ_FIFO               (1<<18)
+
+/* STATUS bit shifts */
+#define VSTATUS                        (1<<0)
+#define HSTATUS                        (1<<1)
+
+/* GPIO bit shifts */
+#define CAM_RST                        (1<<0)
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
new file mode 100644 (file)
index 0000000..740c297
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  linux/include/asm-arm/arch-omap/clock.h
+ *
+ *  Copyright (C) 2004 - 2005 Nokia corporation
+ *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *  Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_OMAP_CLOCK_H
+#define __ARCH_ARM_OMAP_CLOCK_H
+
+struct module;
+
+struct clk {
+       struct list_head        node;
+       struct module           *owner;
+       const char              *name;
+       struct clk              *parent;
+       unsigned long           rate;
+       __u32                   flags;
+       void __iomem            *enable_reg;
+       __u8                    enable_bit;
+       __u8                    rate_offset;
+       __u8                    src_offset;
+       __s8                    usecount;
+       void                    (*recalc)(struct clk *);
+       int                     (*set_rate)(struct clk *, unsigned long);
+       long                    (*round_rate)(struct clk *, unsigned long);
+       void                    (*init)(struct clk *);
+       int                     (*enable)(struct clk *);
+       void                    (*disable)(struct clk *);
+};
+
+struct clk_functions {
+       int             (*clk_enable)(struct clk *clk);
+       void            (*clk_disable)(struct clk *clk);
+       int             (*clk_use)(struct clk *clk);
+       void            (*clk_unuse)(struct clk *clk);
+       long            (*clk_round_rate)(struct clk *clk, unsigned long rate);
+       int             (*clk_set_rate)(struct clk *clk, unsigned long rate);
+       int             (*clk_set_parent)(struct clk *clk, struct clk *parent);
+       struct clk *    (*clk_get_parent)(struct clk *clk);
+       void            (*clk_allow_idle)(struct clk *clk);
+       void            (*clk_deny_idle)(struct clk *clk);
+};
+
+extern unsigned int mpurate;
+extern struct list_head clocks;
+extern spinlock_t clockfw_lock;
+
+extern int clk_init(struct clk_functions * custom_clocks);
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+extern void propagate_rate(struct clk *clk);
+extern void followparent_recalc(struct clk * clk);
+extern void clk_allow_idle(struct clk *clk);
+extern void clk_deny_idle(struct clk *clk);
+
+/* Clock flags */
+#define RATE_CKCTL             (1 << 0)        /* Main fixed ratio clocks */
+#define RATE_FIXED             (1 << 1)        /* Fixed clock rate */
+#define RATE_PROPAGATES                (1 << 2)        /* Program children too */
+#define VIRTUAL_CLOCK          (1 << 3)        /* Composite clock from table */
+#define ALWAYS_ENABLED         (1 << 4)        /* Clock cannot be disabled */
+#define ENABLE_REG_32BIT       (1 << 5)        /* Use 32-bit access */
+#define VIRTUAL_IO_ADDRESS     (1 << 6)        /* Clock in virtual address */
+#define CLOCK_IDLE_CONTROL     (1 << 7)
+#define CLOCK_NO_IDLE_PARENT   (1 << 8)
+#define DELAYED_APP            (1 << 9)        /* Delay application of clock */
+#define CONFIG_PARTICIPANT     (1 << 10)       /* Fundamental clock */
+#define CM_MPU_SEL1            (1 << 11)       /* Domain divider/source */
+#define CM_DSP_SEL1            (1 << 12)
+#define CM_GFX_SEL1            (1 << 13)
+#define CM_MODEM_SEL1          (1 << 14)
+#define CM_CORE_SEL1           (1 << 15)       /* Sets divider for many */
+#define CM_CORE_SEL2           (1 << 16)       /* sets parent for GPT */
+#define CM_WKUP_SEL1           (1 << 17)
+#define CM_PLL_SEL1            (1 << 18)
+#define CM_PLL_SEL2            (1 << 19)
+#define CM_SYSCLKOUT_SEL1      (1 << 20)
+#define CLOCK_IN_OMAP730       (1 << 21)
+#define CLOCK_IN_OMAP1510      (1 << 22)
+#define CLOCK_IN_OMAP16XX      (1 << 23)
+#define CLOCK_IN_OMAP242X      (1 << 24)
+#define CLOCK_IN_OMAP243X      (1 << 25)
+
+#endif
index 2a676b4f13b5dedb4eeb9f227f8fa4120b6e66b8..08d58abd82182a1fdd307f1a7ed94a256f86c35d 100644 (file)
@@ -31,6 +31,6 @@ struct sys_timer;
 
 extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
-extern void omap_serial_init(int ports[]);
+extern void omap_serial_init(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
index 1119e2b53e724fb9773c35dcaf793cc7b7df62e0..ec7eb675d9227fea8bb308873d25bda8d4a9ade7 100644 (file)
 
 extern unsigned int system_rev;
 
-#define OMAP_DIE_ID_0          0xfffe1800
-#define OMAP_DIE_ID_1          0xfffe1804
-#define OMAP_PRODUCTION_ID_0   0xfffe2000
-#define OMAP_PRODUCTION_ID_1   0xfffe2004
-#define OMAP32_ID_0            0xfffed400
-#define OMAP32_ID_1            0xfffed404
+#define omap2_cpu_rev()                ((system_rev >> 8) & 0x0f)
 
 /*
  * Test if multicore OMAP support is needed
@@ -50,7 +45,7 @@ extern unsigned int system_rev;
 #  define OMAP_NAME omap730
 # endif
 #endif
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 # ifdef OMAP_NAME
 #  undef  MULTI_OMAP1
 #  define MULTI_OMAP1
@@ -79,9 +74,11 @@ extern unsigned int system_rev;
  * Macros to group OMAP into cpu classes.
  * These can be used in most places.
  * cpu_is_omap7xx():   True for OMAP730
- * cpu_is_omap15xx():  True for OMAP1510 and OMAP5910
+ * cpu_is_omap15xx():  True for OMAP1510, OMAP5910 and OMAP310
  * cpu_is_omap16xx():  True for OMAP1610, OMAP5912 and OMAP1710
- * cpu_is_omap24xx():  True for OMAP2420
+ * cpu_is_omap24xx():  True for OMAP2420, OMAP2422, OMAP2423, OMAP2430
+ * cpu_is_omap242x():  True for OMAP2420, OMAP2422, OMAP2423
+ * cpu_is_omap243x():  True for OMAP2430
  */
 #define GET_OMAP_CLASS (system_rev & 0xff)
 
@@ -91,22 +88,35 @@ static inline int is_omap ##class (void)            \
        return (GET_OMAP_CLASS == (id)) ? 1 : 0;        \
 }
 
+#define GET_OMAP_SUBCLASS      ((system_rev >> 20) & 0x0fff)
+
+#define IS_OMAP_SUBCLASS(subclass, id)                 \
+static inline int is_omap ##subclass (void)            \
+{                                                      \
+       return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;     \
+}
+
 IS_OMAP_CLASS(7xx, 0x07)
 IS_OMAP_CLASS(15xx, 0x15)
 IS_OMAP_CLASS(16xx, 0x16)
 IS_OMAP_CLASS(24xx, 0x24)
 
+IS_OMAP_SUBCLASS(242x, 0x242)
+IS_OMAP_SUBCLASS(243x, 0x243)
+
 #define cpu_is_omap7xx()               0
 #define cpu_is_omap15xx()              0
 #define cpu_is_omap16xx()              0
 #define cpu_is_omap24xx()              0
+#define cpu_is_omap242x()              0
+#define cpu_is_omap243x()              0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
 #  undef  cpu_is_omap7xx
 #  define cpu_is_omap7xx()             is_omap7xx()
 # endif
-# if defined(CONFIG_ARCH_OMAP1510)
+# if defined(CONFIG_ARCH_OMAP15XX)
 #  undef  cpu_is_omap15xx
 #  define cpu_is_omap15xx()            is_omap15xx()
 # endif
@@ -119,7 +129,7 @@ IS_OMAP_CLASS(24xx, 0x24)
 #  undef  cpu_is_omap7xx
 #  define cpu_is_omap7xx()             1
 # endif
-# if defined(CONFIG_ARCH_OMAP1510)
+# if defined(CONFIG_ARCH_OMAP15XX)
 #  undef  cpu_is_omap15xx
 #  define cpu_is_omap15xx()            1
 # endif
@@ -129,13 +139,18 @@ IS_OMAP_CLASS(24xx, 0x24)
 # endif
 # if defined(CONFIG_ARCH_OMAP24XX)
 #  undef  cpu_is_omap24xx
+#  undef  cpu_is_omap242x
+#  undef  cpu_is_omap243x
 #  define cpu_is_omap24xx()            1
+#  define cpu_is_omap242x()            is_omap242x()
+#  define cpu_is_omap243x()            is_omap243x()
 # endif
 #endif
 
 /*
  * Macros to detect individual cpu types.
  * These are only rarely needed.
+ * cpu_is_omap330():   True for OMAP330
  * cpu_is_omap730():   True for OMAP730
  * cpu_is_omap1510():  True for OMAP1510
  * cpu_is_omap1610():  True for OMAP1610
@@ -144,6 +159,9 @@ IS_OMAP_CLASS(24xx, 0x24)
  * cpu_is_omap1621():  True for OMAP1621
  * cpu_is_omap1710():  True for OMAP1710
  * cpu_is_omap2420():  True for OMAP2420
+ * cpu_is_omap2422():  True for OMAP2422
+ * cpu_is_omap2423():  True for OMAP2423
+ * cpu_is_omap2430():  True for OMAP2430
  */
 #define GET_OMAP_TYPE  ((system_rev >> 16) & 0xffff)
 
@@ -153,6 +171,7 @@ static inline int is_omap ##type (void)                     \
        return (GET_OMAP_TYPE == (id)) ? 1 : 0;         \
 }
 
+IS_OMAP_TYPE(310, 0x0310)
 IS_OMAP_TYPE(730, 0x0730)
 IS_OMAP_TYPE(1510, 0x1510)
 IS_OMAP_TYPE(1610, 0x1610)
@@ -161,7 +180,11 @@ IS_OMAP_TYPE(5912, 0x1611)
 IS_OMAP_TYPE(1621, 0x1621)
 IS_OMAP_TYPE(1710, 0x1710)
 IS_OMAP_TYPE(2420, 0x2420)
+IS_OMAP_TYPE(2422, 0x2422)
+IS_OMAP_TYPE(2423, 0x2423)
+IS_OMAP_TYPE(2430, 0x2430)
 
+#define cpu_is_omap310()               0
 #define cpu_is_omap730()               0
 #define cpu_is_omap1510()              0
 #define cpu_is_omap1610()              0
@@ -170,31 +193,33 @@ IS_OMAP_TYPE(2420, 0x2420)
 #define cpu_is_omap1621()              0
 #define cpu_is_omap1710()              0
 #define cpu_is_omap2420()              0
+#define cpu_is_omap2422()              0
+#define cpu_is_omap2423()              0
+#define cpu_is_omap2430()              0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
 #  undef  cpu_is_omap730
 #  define cpu_is_omap730()             is_omap730()
 # endif
-# if defined(CONFIG_ARCH_OMAP1510)
-#  undef  cpu_is_omap1510
-#  define cpu_is_omap1510()            is_omap1510()
-# endif
 #else
 # if defined(CONFIG_ARCH_OMAP730)
 #  undef  cpu_is_omap730
 #  define cpu_is_omap730()             1
 # endif
-# if defined(CONFIG_ARCH_OMAP1510)
-#  undef  cpu_is_omap1510
-#  define cpu_is_omap1510()            1
-# endif
 #endif
 
 /*
  * Whether we have MULTI_OMAP1 or not, we still need to distinguish
- * between 1611B/5912 and 1710.
+ * between 330 vs. 1510 and 1611B/5912 vs. 1710.
  */
+#if defined(CONFIG_ARCH_OMAP15XX)
+# undef  cpu_is_omap310
+# undef  cpu_is_omap1510
+# define cpu_is_omap310()              is_omap310()
+# define cpu_is_omap1510()             is_omap1510()
+#endif
+
 #if defined(CONFIG_ARCH_OMAP16XX)
 # undef  cpu_is_omap1610
 # undef  cpu_is_omap1611
@@ -208,9 +233,20 @@ IS_OMAP_TYPE(2420, 0x2420)
 # define cpu_is_omap1710()             is_omap1710()
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2420)
-#  undef  cpu_is_omap2420
-#  define cpu_is_omap2420()            1
+#if defined(CONFIG_ARCH_OMAP24XX)
+# undef  cpu_is_omap2420
+# undef  cpu_is_omap2422
+# undef  cpu_is_omap2423
+# undef  cpu_is_omap2430
+# define cpu_is_omap2420()             is_omap2420()
+# define cpu_is_omap2422()             is_omap2422()
+# define cpu_is_omap2423()             is_omap2423()
+# define cpu_is_omap2430()             is_omap2430()
 #endif
 
+/* Macros to detect if we have OMAP1 or OMAP2 */
+#define cpu_class_is_omap1()   (cpu_is_omap730() || cpu_is_omap15xx() || \
+                               cpu_is_omap16xx())
+#define cpu_class_is_omap2()   cpu_is_omap24xx()
+
 #endif
index 04ebef5c6e95d180142d3e25e938630705b4341c..ccbcb580a5c17b90326c8c9c679cfe737d0d908d 100644 (file)
 #define __ASM_ARCH_DMA_H
 
 #define MAX_DMA_ADDRESS                        0xffffffff
+#define MAX_DMA_CHANNELS               0
+
+/* Hardware registers for omap1 */
+#define OMAP_DMA_BASE                  (0xfffed800)
+#define OMAP_DMA_GCR                   (OMAP_DMA_BASE + 0x400)
+#define OMAP_DMA_GSCR                  (OMAP_DMA_BASE + 0x404)
+#define OMAP_DMA_GRST                  (OMAP_DMA_BASE + 0x408)
+#define OMAP_DMA_HW_ID                 (OMAP_DMA_BASE + 0x442)
+#define OMAP_DMA_PCH2_ID               (OMAP_DMA_BASE + 0x444)
+#define OMAP_DMA_PCH0_ID               (OMAP_DMA_BASE + 0x446)
+#define OMAP_DMA_PCH1_ID               (OMAP_DMA_BASE + 0x448)
+#define OMAP_DMA_PCHG_ID               (OMAP_DMA_BASE + 0x44a)
+#define OMAP_DMA_PCHD_ID               (OMAP_DMA_BASE + 0x44c)
+#define OMAP_DMA_CAPS_0_U              (OMAP_DMA_BASE + 0x44e)
+#define OMAP_DMA_CAPS_0_L              (OMAP_DMA_BASE + 0x450)
+#define OMAP_DMA_CAPS_1_U              (OMAP_DMA_BASE + 0x452)
+#define OMAP_DMA_CAPS_1_L              (OMAP_DMA_BASE + 0x454)
+#define OMAP_DMA_CAPS_2                        (OMAP_DMA_BASE + 0x456)
+#define OMAP_DMA_CAPS_3                        (OMAP_DMA_BASE + 0x458)
+#define OMAP_DMA_CAPS_4                        (OMAP_DMA_BASE + 0x45a)
+#define OMAP_DMA_PCH2_SR               (OMAP_DMA_BASE + 0x460)
+#define OMAP_DMA_PCH0_SR               (OMAP_DMA_BASE + 0x480)
+#define OMAP_DMA_PCH1_SR               (OMAP_DMA_BASE + 0x482)
+#define OMAP_DMA_PCHD_SR               (OMAP_DMA_BASE + 0x4c0)
+
+/* Hardware registers for omap2 */
+#define OMAP24XX_DMA_BASE              (L4_24XX_BASE + 0x56000)
+#define OMAP_DMA4_REVISION             (OMAP24XX_DMA_BASE + 0x00)
+#define OMAP_DMA4_GCR_REG              (OMAP24XX_DMA_BASE + 0x78)
+#define OMAP_DMA4_IRQSTATUS_L0         (OMAP24XX_DMA_BASE + 0x08)
+#define OMAP_DMA4_IRQSTATUS_L1         (OMAP24XX_DMA_BASE + 0x0c)
+#define OMAP_DMA4_IRQSTATUS_L2         (OMAP24XX_DMA_BASE + 0x10)
+#define OMAP_DMA4_IRQSTATUS_L3         (OMAP24XX_DMA_BASE + 0x14)
+#define OMAP_DMA4_IRQENABLE_L0         (OMAP24XX_DMA_BASE + 0x18)
+#define OMAP_DMA4_IRQENABLE_L1         (OMAP24XX_DMA_BASE + 0x1c)
+#define OMAP_DMA4_IRQENABLE_L2         (OMAP24XX_DMA_BASE + 0x20)
+#define OMAP_DMA4_IRQENABLE_L3         (OMAP24XX_DMA_BASE + 0x24)
+#define OMAP_DMA4_SYSSTATUS            (OMAP24XX_DMA_BASE + 0x28)
+#define OMAP_DMA4_CAPS_0               (OMAP24XX_DMA_BASE + 0x64)
+#define OMAP_DMA4_CAPS_2               (OMAP24XX_DMA_BASE + 0x6c)
+#define OMAP_DMA4_CAPS_3               (OMAP24XX_DMA_BASE + 0x70)
+#define OMAP_DMA4_CAPS_4               (OMAP24XX_DMA_BASE + 0x74)
+
+#ifdef CONFIG_ARCH_OMAP1
 
 #define OMAP_LOGICAL_DMA_CH_COUNT      17
 
+/* Common channel specific registers for omap1 */
+#define OMAP_DMA_CSDP_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x00)
+#define OMAP_DMA_CCR_REG(n)            __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x02)
+#define OMAP_DMA_CICR_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x04)
+#define OMAP_DMA_CSR_REG(n)            __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x06)
+#define OMAP_DMA_CEN_REG(n)            __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x10)
+#define OMAP_DMA_CFN_REG(n)            __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x12)
+#define OMAP_DMA_CSFI_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x14)
+#define OMAP_DMA_CSEI_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x16)
+#define OMAP_DMA_CSAC_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x18)
+#define OMAP_DMA_CDAC_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x1a)
+#define OMAP_DMA_CDEI_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x1c)
+#define OMAP_DMA_CDFI_REG(n)           __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x1e)
+#define OMAP_DMA_CLNK_CTRL_REG(n)      __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x28)
+
+#else
+
+#define OMAP_LOGICAL_DMA_CH_COUNT      32      /* REVISIT: Is this 32 + 2? */
+
+/* Common channel specific registers for omap2 */
+#define OMAP_DMA_CCR_REG(n)            __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x80)
+#define OMAP_DMA_CLNK_CTRL_REG(n)      __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x84)
+#define OMAP_DMA_CICR_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x88)
+#define OMAP_DMA_CSR_REG(n)            __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x8c)
+#define OMAP_DMA_CSDP_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x90)
+#define OMAP_DMA_CEN_REG(n)            __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x94)
+#define OMAP_DMA_CFN_REG(n)            __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x98)
+#define OMAP_DMA_CSEI_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa4)
+#define OMAP_DMA_CSFI_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa8)
+#define OMAP_DMA_CDEI_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xac)
+#define OMAP_DMA_CDFI_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb0)
+#define OMAP_DMA_CSAC_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb4)
+#define OMAP_DMA_CDAC_REG(n)           __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb8)
+
+#endif
+
+/* Channel specific registers only on omap1 */
+#define OMAP1_DMA_CSSA_L_REG(n)                __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x08)
+#define OMAP1_DMA_CSSA_U_REG(n)                __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x0a)
+#define OMAP1_DMA_CDSA_L_REG(n)                __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x0c)
+#define OMAP1_DMA_CDSA_U_REG(n)                __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x0e)
+#define OMAP1_DMA_COLOR_L_REG(n)       __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x20)
+#define OMAP1_DMA_CCR2_REG(n)          __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x24)
+#define OMAP1_DMA_COLOR_U_REG(n)       __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x22)
+#define OMAP1_DMA_LCH_CTRL_REG(n)      __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x2a)
+
+/* Channel specific registers only on omap2 */
+#define OMAP2_DMA_CSSA_REG(n)          __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x9c)
+#define OMAP2_DMA_CDSA_REG(n)          __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa0)
+#define OMAP2_DMA_CCEN_REG(n)          __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xbc)
+#define OMAP2_DMA_CCFN_REG(n)          __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc0)
+#define OMAP2_DMA_COLOR_REG(n)         __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc4)
+
+/*----------------------------------------------------------------------------*/
+
+/* DMA channels for omap1 */
 #define OMAP_DMA_NO_DEVICE             0
 #define OMAP_DMA_MCSI1_TX              1
 #define OMAP_DMA_MCSI1_RX              2
 #define OMAP_DMA_MMC2_RX               55
 #define OMAP_DMA_CRYPTO_DES_OUT                56
 
+/* DMA channels for 24xx */
+#define OMAP24XX_DMA_NO_DEVICE         0
+#define OMAP24XX_DMA_XTI_DMA           1       /* S_DMA_0 */
+#define OMAP24XX_DMA_EXT_NDMA_REQ0     2       /* S_DMA_1 */
+#define OMAP24XX_DMA_EXT_NDMA_REQ1     3       /* S_DMA_2 */
+#define OMAP24XX_DMA_GPMC              4       /* S_DMA_3 */
+#define OMAP24XX_DMA_GFX               5       /* S_DMA_4 */
+#define OMAP24XX_DMA_DSS               6       /* S_DMA_5 */
+#define OMAP24XX_DMA_VLYNQ_TX          7       /* S_DMA_6 */
+#define OMAP24XX_DMA_CWT               8       /* S_DMA_7 */
+#define OMAP24XX_DMA_AES_TX            9       /* S_DMA_8 */
+#define OMAP24XX_DMA_AES_RX            10      /* S_DMA_9 */
+#define OMAP24XX_DMA_DES_TX            11      /* S_DMA_10 */
+#define OMAP24XX_DMA_DES_RX            12      /* S_DMA_11 */
+#define OMAP24XX_DMA_SHA1MD5_RX                13      /* S_DMA_12 */
 
-#define OMAP_DMA_BASE                  (0xfffed800)
-#define OMAP_DMA_GCR                   (OMAP_DMA_BASE + 0x400)
-#define OMAP_DMA_GSCR                  (OMAP_DMA_BASE + 0x404)
-#define OMAP_DMA_GRST                  (OMAP_DMA_BASE + 0x408)
-#define OMAP_DMA_HW_ID                 (OMAP_DMA_BASE + 0x442)
-#define OMAP_DMA_PCH2_ID               (OMAP_DMA_BASE + 0x444)
-#define OMAP_DMA_PCH0_ID               (OMAP_DMA_BASE + 0x446)
-#define OMAP_DMA_PCH1_ID               (OMAP_DMA_BASE + 0x448)
-#define OMAP_DMA_PCHG_ID               (OMAP_DMA_BASE + 0x44a)
-#define OMAP_DMA_PCHD_ID               (OMAP_DMA_BASE + 0x44c)
-#define OMAP_DMA_CAPS_0_U              (OMAP_DMA_BASE + 0x44e)
-#define OMAP_DMA_CAPS_0_L              (OMAP_DMA_BASE + 0x450)
-#define OMAP_DMA_CAPS_1_U              (OMAP_DMA_BASE + 0x452)
-#define OMAP_DMA_CAPS_1_L              (OMAP_DMA_BASE + 0x454)
-#define OMAP_DMA_CAPS_2                        (OMAP_DMA_BASE + 0x456)
-#define OMAP_DMA_CAPS_3                        (OMAP_DMA_BASE + 0x458)
-#define OMAP_DMA_CAPS_4                        (OMAP_DMA_BASE + 0x45a)
-#define OMAP_DMA_PCH2_SR               (OMAP_DMA_BASE + 0x460)
-#define OMAP_DMA_PCH0_SR               (OMAP_DMA_BASE + 0x480)
-#define OMAP_DMA_PCH1_SR               (OMAP_DMA_BASE + 0x482)
-#define OMAP_DMA_PCHD_SR               (OMAP_DMA_BASE + 0x4c0)
+#define OMAP24XX_DMA_EAC_AC_RD         17      /* S_DMA_16 */
+#define OMAP24XX_DMA_EAC_AC_WR         18      /* S_DMA_17 */
+#define OMAP24XX_DMA_EAC_MD_UL_RD      19      /* S_DMA_18 */
+#define OMAP24XX_DMA_EAC_MD_UL_WR      20      /* S_DMA_19 */
+#define OMAP24XX_DMA_EAC_MD_DL_RD      21      /* S_DMA_20 */
+#define OMAP24XX_DMA_EAC_MD_DL_WR      22      /* S_DMA_21 */
+#define OMAP24XX_DMA_EAC_BT_UL_RD      23      /* S_DMA_22 */
+#define OMAP24XX_DMA_EAC_BT_UL_WR      24      /* S_DMA_23 */
+#define OMAP24XX_DMA_EAC_BT_DL_RD      25      /* S_DMA_24 */
+#define OMAP24XX_DMA_EAC_BT_DL_WR      26      /* S_DMA_25 */
+#define OMAP24XX_DMA_I2C1_TX           27      /* S_DMA_26 */
+#define OMAP24XX_DMA_I2C1_RX           28      /* S_DMA_27 */
+#define OMAP24XX_DMA_I2C2_TX           29      /* S_DMA_28 */
+#define OMAP24XX_DMA_I2C2_RX           30      /* S_DMA_29 */
+#define OMAP24XX_DMA_MCBSP1_TX         31      /* SDMA_30 */
+#define OMAP24XX_DMA_MCBSP1_RX         32      /* SDMA_31 */
+#define OMAP24XX_DMA_MCBSP2_TX         33      /* SDMA_32 */
+#define OMAP24XX_DMA_MCBSP2_RX         34      /* SDMA_33 */
+#define OMAP24XX_DMA_SPI1_TX0          35      /* SDMA_34 */
+#define OMAP24XX_DMA_SPI1_RX0          36      /* SDMA_35 */
+#define OMAP24XX_DMA_SPI1_TX1          37      /* SDMA_36 */
+#define OMAP24XX_DMA_SPI1_RX1          38      /* SDMA_37 */
+#define OMAP24XX_DMA_SPI1_TX2          39      /* SDMA_38 */
+#define OMAP24XX_DMA_SPI1_RX2          40      /* SDMA_39 */
+#define OMAP24XX_DMA_SPI1_TX3          41      /* SDMA_40 */
+#define OMAP24XX_DMA_SPI1_RX3          42      /* SDMA_41 */
+#define OMAP24XX_DMA_SPI2_TX0          43      /* SDMA_42 */
+#define OMAP24XX_DMA_SPI2_RX0          44      /* SDMA_43 */
+#define OMAP24XX_DMA_SPI2_TX1          45      /* SDMA_44 */
+#define OMAP24XX_DMA_SPI2_RX1          46      /* SDMA_45 */
 
+#define OMAP24XX_DMA_UART1_TX          49      /* SDMA_48 */
+#define OMAP24XX_DMA_UART1_RX          50      /* SDMA_49 */
+#define OMAP24XX_DMA_UART2_TX          51      /* SDMA_50 */
+#define OMAP24XX_DMA_UART2_RX          52      /* SDMA_51 */
+#define OMAP24XX_DMA_UART3_TX          53      /* SDMA_52 */
+#define OMAP24XX_DMA_UART3_RX          54      /* SDMA_53 */
+#define OMAP24XX_DMA_USB_W2FC_TX0      55      /* SDMA_54 */
+#define OMAP24XX_DMA_USB_W2FC_RX0      56      /* SDMA_55 */
+#define OMAP24XX_DMA_USB_W2FC_TX1      57      /* SDMA_56 */
+#define OMAP24XX_DMA_USB_W2FC_RX1      58      /* SDMA_57 */
+#define OMAP24XX_DMA_USB_W2FC_TX2      59      /* SDMA_58 */
+#define OMAP24XX_DMA_USB_W2FC_RX2      60      /* SDMA_59 */
+#define OMAP24XX_DMA_MMC1_TX           61      /* SDMA_60 */
+#define OMAP24XX_DMA_MMC1_RX           62      /* SDMA_61 */
+#define OMAP24XX_DMA_MS                        63      /* SDMA_62 */
+
+/*----------------------------------------------------------------------------*/
+
+/* Hardware registers for LCD DMA */
 #define OMAP1510_DMA_LCD_BASE          (0xfffedb00)
 #define OMAP1510_DMA_LCD_CTRL          (OMAP1510_DMA_LCD_BASE + 0x00)
 #define OMAP1510_DMA_LCD_TOP_F1_L      (OMAP1510_DMA_LCD_BASE + 0x02)
 #define OMAP1510_DMA_LCD_BOT_F1_U      (OMAP1510_DMA_LCD_BASE + 0x08)
 
 #define OMAP1610_DMA_LCD_BASE          (0xfffee300)
-#define OMAP1610_DMA_LCD_CSDP          (OMAP1610_DMA_LCD_BASE + 0xc0)
+#define OMAP1610_DMA_LCD_CSDP          (OMAP1610_DMA_LCD_BASE + 0xc0)
 #define OMAP1610_DMA_LCD_CCR           (OMAP1610_DMA_LCD_BASE + 0xc2)
 #define OMAP1610_DMA_LCD_CTRL          (OMAP1610_DMA_LCD_BASE + 0xc4)
 #define OMAP1610_DMA_LCD_TOP_B1_L      (OMAP1610_DMA_LCD_BASE + 0xc8)
 #define OMAP1610_DMA_LCD_LCH_CTRL      (OMAP1610_DMA_LCD_BASE + 0xea)
 #define OMAP1610_DMA_LCD_SRC_FI_B1_U   (OMAP1610_DMA_LCD_BASE + 0xf4)
 
-
-/* Every LCh has its own set of the registers below */
-#define OMAP_DMA_CSDP(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x00)
-#define OMAP_DMA_CCR(n)                        (OMAP_DMA_BASE + 0x40 * (n) + 0x02)
-#define OMAP_DMA_CICR(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x04)
-#define OMAP_DMA_CSR(n)                        (OMAP_DMA_BASE + 0x40 * (n) + 0x06)
-#define OMAP_DMA_CSSA_L(n)             (OMAP_DMA_BASE + 0x40 * (n) + 0x08)
-#define OMAP_DMA_CSSA_U(n)             (OMAP_DMA_BASE + 0x40 * (n) + 0x0a)
-#define OMAP_DMA_CDSA_L(n)             (OMAP_DMA_BASE + 0x40 * (n) + 0x0c)
-#define OMAP_DMA_CDSA_U(n)             (OMAP_DMA_BASE + 0x40 * (n) + 0x0e)
-#define OMAP_DMA_CEN(n)                        (OMAP_DMA_BASE + 0x40 * (n) + 0x10)
-#define OMAP_DMA_CFN(n)                        (OMAP_DMA_BASE + 0x40 * (n) + 0x12)
-#define OMAP_DMA_CSFI(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x14)
-#define OMAP_DMA_CSEI(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x16)
-#define OMAP_DMA_CSAC(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x18)
-#define OMAP_DMA_CDAC(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x1a)
-#define OMAP_DMA_CDEI(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x1c)
-#define OMAP_DMA_CDFI(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x1e)
-#define OMAP_DMA_COLOR_L(n)            (OMAP_DMA_BASE + 0x40 * (n) + 0x20)
-#define OMAP_DMA_COLOR_U(n)            (OMAP_DMA_BASE + 0x40 * (n) + 0x22)
-#define OMAP_DMA_CCR2(n)               (OMAP_DMA_BASE + 0x40 * (n) + 0x24)
-#define OMAP_DMA_CLNK_CTRL(n)          (OMAP_DMA_BASE + 0x40 * (n) + 0x28)
-#define OMAP_DMA_LCH_CTRL(n)           (OMAP_DMA_BASE + 0x40 * (n) + 0x2a)
-
-#define OMAP_DMA_TOUT_IRQ              (1 << 0)
+#define OMAP_DMA_TOUT_IRQ              (1 << 0)        /* Only on omap1 */
 #define OMAP_DMA_DROP_IRQ              (1 << 1)
 #define OMAP_DMA_HALF_IRQ              (1 << 2)
 #define OMAP_DMA_FRAME_IRQ             (1 << 3)
 #define OMAP_DMA_LAST_IRQ              (1 << 4)
 #define OMAP_DMA_BLOCK_IRQ             (1 << 5)
-#define OMAP_DMA_SYNC_IRQ              (1 << 6)
+#define OMAP1_DMA_SYNC_IRQ             (1 << 6)
+#define OMAP2_DMA_PKT_IRQ              (1 << 7)
+#define OMAP2_DMA_TRANS_ERR_IRQ                (1 << 8)
+#define OMAP2_DMA_SECURE_ERR_IRQ       (1 << 9)
+#define OMAP2_DMA_SUPERVISOR_ERR_IRQ   (1 << 10)
+#define OMAP2_DMA_MISALIGNED_ERR_IRQ   (1 << 11)
 
 #define OMAP_DMA_DATA_TYPE_S8          0x00
 #define OMAP_DMA_DATA_TYPE_S16         0x01
@@ -194,6 +318,7 @@ enum {
        OMAP_LCD_DMA_B2_BOTTOM
 };
 
+/* REVISIT: Check if BURST_4 is really 1 (or 2) */
 enum omap_dma_burst_mode {
        OMAP_DMA_DATA_BURST_DIS = 0,
        OMAP_DMA_DATA_BURST_4,
@@ -206,6 +331,31 @@ enum omap_dma_color_mode {
        OMAP_DMA_TRANSPARENT_COPY
 };
 
+struct omap_dma_channel_params {
+       int data_type;          /* data type 8,16,32 */
+       int elem_count;         /* number of elements in a frame */
+       int frame_count;        /* number of frames in a element */
+
+       int src_port;           /* Only on OMAP1 REVISIT: Is this needed? */
+       int src_amode;          /* constant , post increment, indexed , double indexed */
+       int src_start;          /* source address : physical */
+       int src_ei;             /* source element index */
+       int src_fi;             /* source frame index */
+
+       int dst_port;           /* Only on OMAP1 REVISIT: Is this needed? */
+       int dst_amode;          /* constant , post increment, indexed , double indexed */
+       int dst_start;          /* source address : physical */
+       int dst_ei;             /* source element index */
+       int dst_fi;             /* source frame index */
+
+       int trigger;            /* trigger attached if the channel is synchronized */
+       int sync_mode;          /* sycn on element, frame , block or packet */
+       int src_or_dst_synch;   /* source synch(1) or destination synch(0) */
+
+       int ie;                 /* interrupt enabled */
+};
+
+
 extern void omap_set_dma_priority(int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
                            void (* callback)(int lch, u16 ch_status, void *data),
@@ -217,24 +367,30 @@ extern void omap_start_dma(int lch);
 extern void omap_stop_dma(int lch);
 extern void omap_set_dma_transfer_params(int lch, int data_type,
                                         int elem_count, int frame_count,
-                                        int sync_mode);
+                                        int sync_mode,
+                                        int dma_trigger, int src_or_dst_synch);
 extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
                                    u32 color);
 
 extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
-                                   unsigned long src_start);
+                                   unsigned long src_start,
+                                   int src_ei, int src_fi);
 extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
 extern void omap_set_dma_src_data_pack(int lch, int enable);
 extern void omap_set_dma_src_burst_mode(int lch,
                                        enum omap_dma_burst_mode burst_mode);
 
 extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
-                                    unsigned long dest_start);
+                                    unsigned long dest_start,
+                                    int dst_ei, int dst_fi);
 extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
 extern void omap_set_dma_dest_data_pack(int lch, int enable);
 extern void omap_set_dma_dest_burst_mode(int lch,
                                         enum omap_dma_burst_mode burst_mode);
 
+extern void omap_set_dma_params(int lch,
+                               struct omap_dma_channel_params * params);
+
 extern void omap_dma_link_lch (int lch_head, int lch_queue);
 extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
 
@@ -244,9 +400,6 @@ extern int omap_get_dma_src_addr_counter(int lch);
 extern void omap_clear_dma(int lch);
 extern int omap_dma_running(void);
 
-/* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
-extern int omap_dma_in_1510_mode(void);
-
 /* LCD DMA functions */
 extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
                                void *data);
index 0d29b9c56a957c9c83e76e1f5730fcbea5957da0..e857ed9bf02b79786452c75f8dca56e3006fb06d 100644 (file)
 
 #if defined(CONFIG_ARCH_OMAP1)
 
+#if defined(CONFIG_ARCH_OMAP730) && \
+       (defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX))
+#error "FIXME: OMAP730 doesn't support multiple-OMAP"  
+#elif defined(CONFIG_ARCH_OMAP730)
+#define INT_IH2_IRQ            INT_730_IH2_IRQ
+#elif defined(CONFIG_ARCH_OMAP15XX)
+#define INT_IH2_IRQ            INT_1510_IH2_IRQ
+#elif defined(CONFIG_ARCH_OMAP16XX)
+#define INT_IH2_IRQ            INT_1610_IH2_IRQ
+#else
+#warning "IH2 IRQ defaulted"
+#define INT_IH2_IRQ            INT_1510_IH2_IRQ
+#endif
+
                .macro  disable_fiq
                .endm
 
index 676807dc50e127fe04ef91be508c48a64ce86ebd..6a883e0bdbb803cf9f5a6b60ab5a1e5906623ca7 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __ASM_ARCH_OMAP_FPGA_H
 #define __ASM_ARCH_OMAP_FPGA_H
 
-#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP1510)
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
 extern void omap1510_fpga_init_irq(void);
 #else
 #define omap1510_fpga_init_irq()       (0)
@@ -77,6 +77,8 @@ struct h2p2_dbg_fpga {
 #define H2P2_DBG_FPGA_LOAD_METER_SIZE  11
 #define H2P2_DBG_FPGA_LOAD_METER_MASK  ((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
 
+#define H2P2_DBG_FPGA_P2_LED_TIMER             (1 << 0)
+#define H2P2_DBG_FPGA_P2_LED_IDLE              (1 << 1)
 
 /*
  * ---------------------------------------------------------------------------
index 74cb2b93b70024f39bf135781e0afde230153af5..1b3885741ac1ca05f83cdbf9a7b8090c7cd11c13 100644 (file)
@@ -67,7 +67,7 @@
 
 #define OMAP_GPIO_IRQ(nr)      (OMAP_GPIO_IS_MPUIO(nr) ? \
                                 IH_MPUIO_BASE + ((nr) & 0x0f) : \
-                                IH_GPIO_BASE + ((nr) & 0x3f))
+                                IH_GPIO_BASE + (nr))
 
 extern int omap_gpio_init(void);       /* Call from board init only */
 extern int omap_request_gpio(int gpio);
diff --git a/include/asm-arm/arch-omap/gpioexpander.h b/include/asm-arm/arch-omap/gpioexpander.h
new file mode 100644 (file)
index 0000000..7a43b0a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-omap/gpioexpander.h
+ *
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H
+#define __ASM_ARCH_OMAP_GPIOEXPANDER_H
+
+/* Function Prototypes for GPIO Expander functions */
+
+int read_gpio_expa(u8 *, int);
+int write_gpio_expa(u8 , int);
+
+#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */
index 60201e1dd6ad72b2eb05e3e81f1ae014fc10fc9b..5406b875c422212911497b10aa64198918aafa01 100644 (file)
 #define OMAP_LPG2_LCR                  (OMAP_LPG2_BASE + 0x00)
 #define OMAP_LPG2_PMR                  (OMAP_LPG2_BASE + 0x04)
 
-#ifndef __ASSEMBLER__
-
 /*
  * ---------------------------------------------------------------------------
  * Processor specific defines
 
 #include "omap730.h"
 #include "omap1510.h"
-
-#ifdef CONFIG_ARCH_OMAP24XX
 #include "omap24xx.h"
-#endif
-
 #include "omap16xx.h"
 
+#ifndef __ASSEMBLER__
+
 /*
  * ---------------------------------------------------------------------------
  * Board specific defines
index 3d5bcd54508215ac5036cc7038743d933c35ae19..f5bcc9a1aed645b9a1703cafc5308bc2d8e668ec 100644 (file)
  * ----------------------------------------------------------------------------
  */
 
+#define PCIO_BASE      0
+
 #if defined(CONFIG_ARCH_OMAP1)
+
 #define IO_PHYS                0xFFFB0000
-#define IO_OFFSET      -0x01000000     /* Virtual IO = 0xfefb0000 */
+#define IO_OFFSET      0x01000000      /* Virtual IO = 0xfefb0000 */
 #define IO_SIZE                0x40000
+#define IO_VIRT                (IO_PHYS - IO_OFFSET)
+#define IO_ADDRESS(pa) ((pa) - IO_OFFSET)
+#define io_p2v(pa)     ((pa) - IO_OFFSET)
+#define io_v2p(va)     ((va) + IO_OFFSET)
 
 #elif defined(CONFIG_ARCH_OMAP2)
-#define IO_PHYS                0x48000000      /* L4 peripherals; other stuff has to be mapped *
-                                        * manually. */
-#define IO_OFFSET      0x90000000      /* Virtual IO = 0xd8000000 */
-#define IO_SIZE                0x08000000
-#endif
 
-#define IO_VIRT                (IO_PHYS + IO_OFFSET)
-#define IO_ADDRESS(x)  ((x) + IO_OFFSET)
-#define PCIO_BASE      0
-#define io_p2v(x)      ((x) + IO_OFFSET)
-#define io_v2p(x)      ((x) - IO_OFFSET)
+/* We map both L3 and L4 on OMAP2 */
+#define L3_24XX_PHYS   L3_24XX_BASE    /* 0x68000000 */
+#define L3_24XX_VIRT   0xf8000000
+#define L3_24XX_SIZE   SZ_1M           /* 44kB of 128MB used, want 1MB sect */
+#define L4_24XX_PHYS   L4_24XX_BASE    /* 0x48000000 */
+#define L4_24XX_VIRT   0xd8000000
+#define L4_24XX_SIZE   SZ_1M           /* 1MB of 128MB used, want 1MB sect */
+#define IO_OFFSET      0x90000000
+#define IO_ADDRESS(pa) ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
+#define io_p2v(pa)     ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
+#define io_v2p(va)     ((va) - IO_OFFSET)      /* Works for L3 and L4 */
+
+#endif
 
 #ifndef __ASSEMBLER__
 
index 74e108ccac168fc34444731e59611d82eca6403f..9779686bdcebbe412f5ece3648ccb552e7f8a6e3 100644 (file)
@@ -22,8 +22,8 @@
  *      are different.
  */
 
-#ifndef __ASM_ARCH_OMAP1510_IRQS_H
-#define __ASM_ARCH_OMAP1510_IRQS_H
+#ifndef __ASM_ARCH_OMAP15XX_IRQS_H
+#define __ASM_ARCH_OMAP15XX_IRQS_H
 
 /*
  * IRQ numbers for interrupt handler 1
@@ -31,7 +31,6 @@
  * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
  *
  */
-#define INT_IH2_IRQ            0
 #define INT_CAMERA             1
 #define INT_FIQ                        3
 #define INT_RTDX               6
@@ -60,6 +59,7 @@
 /*
  * OMAP-1510 specific IRQ numbers for interrupt handler 1
  */
+#define INT_1510_IH2_IRQ       0
 #define INT_1510_RES2          2
 #define INT_1510_SPI_TX                4
 #define INT_1510_SPI_RX                5
@@ -71,6 +71,7 @@
 /*
  * OMAP-1610 specific IRQ numbers for interrupt handler 1
  */
+#define INT_1610_IH2_IRQ       0
 #define INT_1610_IH2_FIQ       2
 #define INT_1610_McBSP2_TX     4
 #define INT_1610_McBSP2_RX     5
 #define INT_730_DMA_CH15       (62 + IH2_BASE)
 #define INT_730_NAND           (63 + IH2_BASE)
 
+#define INT_24XX_SYS_NIRQ      7
+#define INT_24XX_SDMA_IRQ0     12
+#define INT_24XX_SDMA_IRQ1     13
+#define INT_24XX_SDMA_IRQ2     14
+#define INT_24XX_SDMA_IRQ3     15
+#define INT_24XX_DSS_IRQ       25
 #define INT_24XX_GPIO_BANK1    29
 #define INT_24XX_GPIO_BANK2    30
 #define INT_24XX_GPIO_BANK3    31
index bf545b6e0a26597ff8abc2a856270df6e9f6e057..df50dd53e1dde37f3733887e09e231173394eac0 100644 (file)
@@ -61,7 +61,7 @@
  * Note that the is_lbus_device() test is not very efficient on 1510
  * because of the strncmp().
  */
-#ifdef CONFIG_ARCH_OMAP1510
+#ifdef CONFIG_ARCH_OMAP15XX
 
 /*
  * OMAP-1510 Local Bus address offset
@@ -84,7 +84,7 @@
                                        virt_to_lbus(addr) : \
                                        __virt_to_bus(addr);})
 
-#endif /* CONFIG_ARCH_OMAP1510 */
+#endif /* CONFIG_ARCH_OMAP15XX */
 
 #endif
 
diff --git a/include/asm-arm/arch-omap/menelaus.h b/include/asm-arm/arch-omap/menelaus.h
new file mode 100644 (file)
index 0000000..46be8b8
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * linux/include/asm-arm/arch-omap/menelaus.h
+ *
+ * Functions to access Menelaus power management chip
+ */
+
+#ifndef __ASM_ARCH_MENELAUS_H
+#define __ASM_ARCH_MENELAUS_H
+
+extern void menelaus_mmc_register(void (*callback)(u8 card_mask),
+                                 unsigned long data);
+extern void menelaus_mmc_remove(void);
+extern void menelaus_mmc_opendrain(int enable);
+
+#if defined(CONFIG_ARCH_OMAP24XX) && defined(CONFIG_MENELAUS)
+#define omap_has_menelaus()    1
+#else
+#define omap_has_menelaus()    0
+#endif
+
+#endif
+
index 1b1ad410534908a013515b737a7065c66d51b3bc..ef4f6ead75e81309673a8d57e680424b47bc4976 100644 (file)
@@ -4,7 +4,7 @@
  * Table of the Omap register configurations for the FUNC_MUX and
  * PULL_DWN combinations.
  *
- * Copyright (C) 2003 Nokia Corporation
+ * Copyright (C) 2003 - 2005 Nokia Corporation
  *
  * Written by Tony Lindgren <tony.lindgren@nokia.com>
  *
                                        .pu_pd_reg = PU_PD_SEL_##reg, \
                                        .pu_pd_val = status,
 
+#define MUX_REG_730(reg, mode_offset, mode) .mux_reg_name = "OMAP730_IO_CONF_"#reg, \
+                                       .mux_reg = OMAP730_IO_CONF_##reg, \
+                                       .mask_offset = mode_offset, \
+                                       .mask = mode,
+
+#define PULL_REG_730(reg, bit, status) .pull_name = "OMAP730_IO_CONF_"#reg, \
+                                       .pull_reg = OMAP730_IO_CONF_##reg, \
+                                       .pull_bit = bit, \
+                                       .pull_val = status,
+
 #else
 
 #define MUX_REG(reg, mode_offset, mode) .mux_reg = FUNC_MUX_CTRL_##reg, \
 #define PU_PD_REG(reg, status)         .pu_pd_reg = PU_PD_SEL_##reg, \
                                        .pu_pd_val = status,
 
+#define MUX_REG_730(reg, mode_offset, mode) \
+                                       .mux_reg = OMAP730_IO_CONF_##reg, \
+                                       .mask_offset = mode_offset, \
+                                       .mask = mode,
+
+#define PULL_REG_730(reg, bit, status) .pull_reg = OMAP730_IO_CONF_##reg, \
+                                       .pull_bit = bit, \
+                                       .pull_val = status,
+
 #endif /* CONFIG_OMAP_MUX_DEBUG */
 
 #define MUX_CFG(desc, mux_reg, mode_offset, mode,      \
        PU_PD_REG(pu_pd_reg, pu_pd_status)              \
 },
 
+
+/* 
+ * OMAP730 has a slightly different config for the pin mux.
+ * - config regs are the OMAP730_IO_CONF_x regs (see omap730.h) regs and 
+ *   not the FUNC_MUX_CTRL_x regs from hardware.h
+ * - for pull-up/down, only has one enable bit which is is in the same register 
+ *   as mux config
+ */
+#define MUX_CFG_730(desc, mux_reg, mode_offset, mode,  \
+                  pull_reg, pull_bit, pull_status,     \
+                  pu_pd_reg, pu_pd_status, debug_status)\
+{                                                      \
+       .name =  desc,                                  \
+       .debug = debug_status,                          \
+       MUX_REG_730(mux_reg, mode_offset, mode)         \
+       PULL_REG_730(mux_reg, pull_bit, pull_status)    \
+       PU_PD_REG(pu_pd_reg, pu_pd_status)              \
+},
+
+#define MUX_CFG_24XX(desc, reg_offset, mode,                   \
+                               pull_en, pull_mode, dbg)        \
+{                                                              \
+       .name           = desc,                                 \
+       .debug          = dbg,                                  \
+       .mux_reg        = reg_offset,                           \
+       .mask           = mode,                                 \
+       .pull_val       = pull_en,                              \
+       .pu_pd_val      = pull_mode,                            \
+},     
+        
+
 #define PULL_DISABLED  0
 #define PULL_ENABLED   1
 
 #define PULL_DOWN      0
 #define PULL_UP                1
 
-typedef struct {
+struct pin_config {
        char *name;
        unsigned char busy;
        unsigned char debug;
@@ -108,13 +158,23 @@ typedef struct {
        const char *pu_pd_name;
        const unsigned int pu_pd_reg;
        const unsigned char pu_pd_val;
-} reg_cfg_set;
+};
 
-/*
- * Lookup table for FUNC_MUX and PULL_DWN register combinations for each
- * device. See also reg_cfg_table below for the register values.
- */
-typedef enum {
+enum omap730_index {
+       /* OMAP 730 keyboard */
+       E2_730_KBR0,
+       J7_730_KBR1,
+       E1_730_KBR2,
+       F3_730_KBR3,
+       D2_730_KBR4,
+       C2_730_KBC0,
+       D3_730_KBC1,
+       E4_730_KBC2,
+       F4_730_KBC3,
+       E3_730_KBC4,
+};
+
+enum omap1xxx_index {
        /* UART1 (BT_UART_GATING)*/
        UART1_TX = 0,
        UART1_RTS,
@@ -331,245 +391,34 @@ typedef enum {
        V10_1610_CF_IREQ,
        W10_1610_CF_RESET,
        W11_1610_CF_CD1,
-} reg_cfg_t;
+};
 
-#if defined(__MUX_C__) && defined(CONFIG_OMAP_MUX)
+enum omap24xx_index {
+       /* 24xx I2C */
+       M19_24XX_I2C1_SCL,
+       L15_24XX_I2C1_SDA,
+       J15_24XX_I2C2_SCL,
+       H19_24XX_I2C2_SDA,
 
-/*
- * Table of various FUNC_MUX and PULL_DWN combinations for each device.
- * See also reg_cfg_t above for the lookup table.
- */
-static const reg_cfg_set __initdata_or_module
-reg_cfg_table[] = {
-/*
- *      description            mux  mode   mux  pull pull  pull  pu_pd  pu  dbg
- *                             reg  offset mode reg  bit   ena   reg
- */
-MUX_CFG("UART1_TX",             9,   21,    1,   2,   3,   0,   NA,     0,  0)
-MUX_CFG("UART1_RTS",            9,   12,    1,   2,   0,   0,   NA,     0,  0)
-
-/* UART2 (COM_UART_GATING), conflicts with USB2 */
-MUX_CFG("UART2_TX",             C,   27,    1,   3,   3,   0,   NA,     0,  0)
-MUX_CFG("UART2_RX",             C,   18,    0,   3,   1,   1,   NA,     0,  0)
-MUX_CFG("UART2_CTS",            C,   21,    0,   3,   1,   1,   NA,     0,  0)
-MUX_CFG("UART2_RTS",            C,   24,    1,   3,   2,   0,   NA,     0,  0)
-
-/* UART3 (GIGA_UART_GATING) */
-MUX_CFG("UART3_TX",             6,    0,    1,   0,  30,   0,   NA,     0,  0)
-MUX_CFG("UART3_RX",             6,    3,    0,   0,  31,   1,   NA,     0,  0)
-MUX_CFG("UART3_CTS",            5,   12,    2,   0,  24,   0,   NA,     0,  0)
-MUX_CFG("UART3_RTS",            5,   15,    2,   0,  25,   0,   NA,     0,  0)
-MUX_CFG("UART3_CLKREQ",                 9,   27,    0,   2,   5,   0,   NA,     0,  0)
-MUX_CFG("UART3_BCLK",           A,    0,    0,   2,   6,   0,   NA,     0,  0)
-MUX_CFG("Y15_1610_UART3_RTS",   A,    0,    1,   2,   6,   0,   NA,     0,  0)
-
-/* PWT & PWL, conflicts with UART3 */
-MUX_CFG("PWT",                  6,    0,    2,   0,  30,   0,   NA,     0,  0)
-MUX_CFG("PWL",                  6,    3,    1,   0,  31,   1,   NA,     0,  0)
-
-/* USB internal master generic */
-MUX_CFG("R18_USB_VBUS",                 7,    9,    2,   1,  11,   0,   NA,     0,  1)
-MUX_CFG("R18_1510_USB_GPIO0",   7,    9,    0,   1,  11,   1,   NA,     0,  1)
-/* works around erratum:  W4_USB_PUEN and W4_USB_PUDIS are switched! */
-MUX_CFG("W4_USB_PUEN",          D,    3,    3,   3,   5,   1,   NA,     0,  1)
-MUX_CFG("W4_USB_CLKO",          D,    3,    1,   3,   5,   0,   NA,     0,  1)
-MUX_CFG("W4_USB_HIGHZ",                 D,    3,    4,   3,   5,   0,    3,     0,  1)
-MUX_CFG("W4_GPIO58",            D,    3,    7,   3,   5,   0,    3,     0,  1)
-
-/* USB1 master */
-MUX_CFG("USB1_SUSP",            8,   27,    2,   1,  27,   0,   NA,     0,  1)
-MUX_CFG("USB1_SE0",             9,    0,    2,   1,  28,   0,   NA,     0,  1)
-MUX_CFG("W13_1610_USB1_SE0",    9,    0,    4,   1,  28,   0,   NA,     0,  1)
-MUX_CFG("USB1_TXEN",            9,    3,    2,   1,  29,   0,   NA,     0,  1)
-MUX_CFG("USB1_TXD",             9,   24,    1,   2,   4,   0,   NA,     0,  1)
-MUX_CFG("USB1_VP",              A,    3,    1,   2,   7,   0,   NA,     0,  1)
-MUX_CFG("USB1_VM",              A,    6,    1,   2,   8,   0,   NA,     0,  1)
-MUX_CFG("USB1_RCV",             A,    9,    1,   2,   9,   0,   NA,     0,  1)
-MUX_CFG("USB1_SPEED",           A,   12,    2,   2,  10,   0,   NA,     0,  1)
-MUX_CFG("R13_1610_USB1_SPEED",  A,   12,    5,   2,  10,   0,   NA,     0,  1)
-MUX_CFG("R13_1710_USB1_SEO",    A,   12,    5,   2,  10,   0,   NA,     0,  1)
-
-/* USB2 master */
-MUX_CFG("USB2_SUSP",            B,    3,    1,   2,  17,   0,   NA,     0,  1)
-MUX_CFG("USB2_VP",              B,    6,    1,   2,  18,   0,   NA,     0,  1)
-MUX_CFG("USB2_TXEN",            B,    9,    1,   2,  19,   0,   NA,     0,  1)
-MUX_CFG("USB2_VM",              C,   18,    1,   3,   0,   0,   NA,     0,  1)
-MUX_CFG("USB2_RCV",             C,   21,    1,   3,   1,   0,   NA,     0,  1)
-MUX_CFG("USB2_SE0",             C,   24,    2,   3,   2,   0,   NA,     0,  1)
-MUX_CFG("USB2_TXD",             C,   27,    2,   3,   3,   0,   NA,     0,  1)
-
-/* OMAP-1510 GPIO */
-MUX_CFG("R18_1510_GPIO0",       7,    9,    0,   1,  11,   1,    0,     0,  1)
-MUX_CFG("R19_1510_GPIO1",       7,    6,    0,   1,  10,   1,    0,     0,  1)
-MUX_CFG("M14_1510_GPIO2",       7,    3,    0,   1,   9,   1,    0,     0,  1)
-
-/* OMAP1610 GPIO */
-MUX_CFG("P18_1610_GPIO3",       7,    0,    0,   1,   8,   0,   NA,     0,  1)
-MUX_CFG("Y15_1610_GPIO17",      A,    0,    7,   2,   6,   0,   NA,     0,  1)
-
-/* OMAP-1710 GPIO */
-MUX_CFG("R18_1710_GPIO0",        7,    9,    0,   1,  11,   1,    1,     1,  1)
-MUX_CFG("V2_1710_GPIO10",        F,   27,    1,   4,   3,   1,    4,     1,  1)
-MUX_CFG("N21_1710_GPIO14",       6,    9,    0,   1,   1,   1,    1,     1,  1)
-MUX_CFG("W15_1710_GPIO40",       9,   27,    7,   2,   5,   1,    2,     1,  1)
-
-/* MPUIO */
-MUX_CFG("MPUIO2",               7,   18,    0,   1,  14,   1,   NA,     0,  1)
-MUX_CFG("N15_1610_MPUIO2",      7,   18,    0,   1,  14,   1,    1,     0,  1)
-MUX_CFG("MPUIO4",               7,   15,    0,   1,  13,   1,   NA,     0,  1)
-MUX_CFG("MPUIO5",               7,   12,    0,   1,  12,   1,   NA,     0,  1)
-
-MUX_CFG("T20_1610_MPUIO5",      7,   12,    0,   1,  12,   0,    3,     0,  1)
-MUX_CFG("W11_1610_MPUIO6",     10,   15,    2,   3,   8,   0,    3,     0,  1)
-MUX_CFG("V10_1610_MPUIO7",      A,   24,    2,   2,  14,   0,    2,     0,  1)
-MUX_CFG("W11_1610_MPUIO9",     10,   15,    1,   3,   8,   0,    3,     0,  1)
-MUX_CFG("V10_1610_MPUIO10",     A,   24,    1,   2,  14,   0,    2,     0,  1)
-MUX_CFG("W10_1610_MPUIO11",     A,   18,    2,   2,  11,   0,    2,     0,  1)
-MUX_CFG("E20_1610_MPUIO13",     3,   21,    1,   0,   7,   0,    0,     0,  1)
-MUX_CFG("U20_1610_MPUIO14",     9,    6,    6,   0,  30,   0,    0,     0,  1)
-MUX_CFG("E19_1610_MPUIO15",     3,   18,    1,   0,   6,   0,    0,     0,  1)
-
-/* MCBSP2 */
-MUX_CFG("MCBSP2_CLKR",          C,    6,    0,   2,  27,   1,   NA,     0,  1)
-MUX_CFG("MCBSP2_CLKX",          C,    9,    0,   2,  29,   1,   NA,     0,  1)
-MUX_CFG("MCBSP2_DR",            C,    0,    0,   2,  26,   1,   NA,     0,  1)
-MUX_CFG("MCBSP2_DX",            C,   15,    0,   2,  31,   1,   NA,     0,  1)
-MUX_CFG("MCBSP2_FSR",           C,   12,    0,   2,  30,   1,   NA,     0,  1)
-MUX_CFG("MCBSP2_FSX",           C,    3,    0,   2,  27,   1,   NA,     0,  1)
-
-/* MCBSP3 NOTE: Mode must 1 for clock */
-MUX_CFG("MCBSP3_CLKX",          9,    3,    1,   1,  29,   0,   NA,     0,  1)
-
-/* Misc ballouts */
-MUX_CFG("BALLOUT_V8_ARMIO3",    B,   18,    0,   2,  25,   1,   NA,     0,  1)
-MUX_CFG("N20_HDQ",            6,   18,    1,   1,   4,   0,    1,     4,  0)
-
-/* OMAP-1610 MMC2 */
-MUX_CFG("W8_1610_MMC2_DAT0",    B,   21,    6,   2,  23,   1,    2,     1,  1)
-MUX_CFG("V8_1610_MMC2_DAT1",    B,   27,    6,   2,  25,   1,    2,     1,  1)
-MUX_CFG("W15_1610_MMC2_DAT2",   9,   12,    6,   2,   5,   1,    2,     1,  1)
-MUX_CFG("R10_1610_MMC2_DAT3",   B,   18,    6,   2,  22,   1,    2,     1,  1)
-MUX_CFG("Y10_1610_MMC2_CLK",    B,    3,    6,   2,  17,   0,    2,     0,  1)
-MUX_CFG("Y8_1610_MMC2_CMD",     B,   24,    6,   2,  24,   1,    2,     1,  1)
-MUX_CFG("V9_1610_MMC2_CMDDIR",  B,   12,    6,   2,  20,   0,    2,     1,  1)
-MUX_CFG("V5_1610_MMC2_DATDIR0",         B,   15,    6,   2,  21,   0,    2,     1,  1)
-MUX_CFG("W19_1610_MMC2_DATDIR1", 8,   15,    6,          1,  23,   0,    1,     1,  1)
-MUX_CFG("R18_1610_MMC2_CLKIN",  7,    9,    6,   1,  11,   0,    1,    11,  1)
-
-/* OMAP-1610 External Trace Interface */
-MUX_CFG("M19_1610_ETM_PSTAT0",  5,   27,    1,   0,  29,   0,    0,     0,  1)
-MUX_CFG("L15_1610_ETM_PSTAT1",  5,   24,    1,   0,  28,   0,    0,     0,  1)
-MUX_CFG("L18_1610_ETM_PSTAT2",  5,   21,    1,   0,  27,   0,    0,     0,  1)
-MUX_CFG("L19_1610_ETM_D0",      5,   18,    1,   0,  26,   0,    0,     0,  1)
-MUX_CFG("J19_1610_ETM_D6",      5,    0,    1,   0,  20,   0,    0,     0,  1)
-MUX_CFG("J18_1610_ETM_D7",      5,   27,    1,   0,  19,   0,    0,     0,  1)
-
-/* OMAP16XX GPIO */
-MUX_CFG("P20_1610_GPIO4",       6,   27,    0,   1,   7,   0,    1,     1,  1)
-MUX_CFG("V9_1610_GPIO7",        B,   12,    1,   2,  20,   0,    2,     1,  1)
-MUX_CFG("W8_1610_GPIO9",        B,   21,    0,   2,  23,   0,    2,     1,  1)
-MUX_CFG("N20_1610_GPIO11",       6,   18,    0,   1,   4,   0,    1,     1,  1)
-MUX_CFG("N19_1610_GPIO13",      6,   12,    0,   1,   2,   0,    1,     1,  1)
-MUX_CFG("P10_1610_GPIO22",      C,    0,    7,   2,  26,   0,    2,     1,  1)
-MUX_CFG("V5_1610_GPIO24",       B,   15,    7,   2,  21,   0,    2,     1,  1)
-MUX_CFG("AA20_1610_GPIO_41",    9,    9,    7,   1,  31,   0,    1,     1,  1)
-MUX_CFG("W19_1610_GPIO48",      8,   15,    7,   1,  23,   1,    1,     0,  1)
-MUX_CFG("M7_1610_GPIO62",      10,    0,    0,   4,  24,   0,    4,     0,  1)
-MUX_CFG("V14_16XX_GPIO37",      9,   18,    7,   2,   2,   0,    2,     2,  0)
-MUX_CFG("R9_16XX_GPIO18",       C,   18,    7,   3,   0,   0,    3,     0,  0)
-MUX_CFG("L14_16XX_GPIO49",      6,    3,    7,   0,  31,   0,    0,    31,  0)
-
-/* OMAP-1610 uWire */
-MUX_CFG("V19_1610_UWIRE_SCLK",  8,    6,    0,   1,  20,   0,    1,     1,  1)
-MUX_CFG("U18_1610_UWIRE_SDI",   8,    0,    0,   1,  18,   0,    1,     1,  1)
-MUX_CFG("W21_1610_UWIRE_SDO",   8,    3,    0,   1,  19,   0,    1,     1,  1)
-MUX_CFG("N14_1610_UWIRE_CS0",   8,    9,    1,   1,  21,   0,    1,     1,  1)
-MUX_CFG("P15_1610_UWIRE_CS3",   8,   12,    1,   1,  22,   0,    1,     1,  1)
-MUX_CFG("N15_1610_UWIRE_CS1",   7,   18,    2,   1,  14,   0,   NA,     0,  1)
-
-/* OMAP-1610 Flash */
-MUX_CFG("L3_1610_FLASH_CS2B_OE",10,    6,    1,         NA,   0,   0,   NA,     0,  1)
-MUX_CFG("M8_1610_FLASH_CS2B_WE",10,    3,    1,         NA,   0,   0,   NA,     0,  1)
-
-/* First MMC interface, same on 1510, 1610 and 1710 */
-MUX_CFG("MMC_CMD",              A,   27,    0,   2,  15,   1,    2,     1,  1)
-MUX_CFG("MMC_DAT1",             A,   24,    0,   2,  14,   1,    2,     1,  1)
-MUX_CFG("MMC_DAT2",             A,   18,    0,   2,  12,   1,    2,     1,  1)
-MUX_CFG("MMC_DAT0",             B,    0,    0,   2,  16,   1,    2,     1,  1)
-MUX_CFG("MMC_CLK",              A,   21,    0,  NA,   0,   0,   NA,     0,  1)
-MUX_CFG("MMC_DAT3",            10,   15,    0,   3,   8,   1,    3,     1,  1)
-MUX_CFG("M15_1710_MMC_CLKI",    6,   21,    2,   0,   0,   0,   NA,     0,  1)
-MUX_CFG("P19_1710_MMC_CMDDIR",  6,   24,    6,   0,   0,   0,   NA,     0,  1)
-MUX_CFG("P20_1710_MMC_DATDIR0",         6,   27,    5,   0,   0,   0,   NA,     0,  1)
-
-/* OMAP-1610 USB0 alternate configuration */
-MUX_CFG("W9_USB0_TXEN",                 B,   9,     5,   2,  19,   0,    2,     0,  1)
-MUX_CFG("AA9_USB0_VP",          B,   6,     5,   2,  18,   0,    2,     0,  1)
-MUX_CFG("Y5_USB0_RCV",          C,  21,     5,   3,   1,   0,    1,     0,  1)
-MUX_CFG("R9_USB0_VM",           C,  18,     5,   3,   0,   0,    3,     0,  1)
-MUX_CFG("V6_USB0_TXD",          C,  27,     5,   3,   3,   0,    3,     0,  1)
-MUX_CFG("W5_USB0_SE0",          C,  24,     5,   3,   2,   0,    3,     0,  1)
-MUX_CFG("V9_USB0_SPEED",        B,  12,     5,   2,  20,   0,    2,     0,  1)
-MUX_CFG("Y10_USB0_SUSP",        B,   3,     5,   2,  17,   0,    2,     0,  1)
-
-/* USB2 interface */
-MUX_CFG("W9_USB2_TXEN",                 B,   9,     1,  NA,   0,   0,   NA,     0,  1)
-MUX_CFG("AA9_USB2_VP",          B,   6,     1,  NA,   0,   0,   NA,     0,  1)
-MUX_CFG("Y5_USB2_RCV",          C,  21,     1,  NA,   0,   0,   NA,     0,  1)
-MUX_CFG("R9_USB2_VM",           C,  18,     1,  NA,   0,   0,   NA,     0,  1)
-MUX_CFG("V6_USB2_TXD",          C,  27,     2,  NA,   0,   0,   NA,     0,  1)
-MUX_CFG("W5_USB2_SE0",          C,  24,     2,  NA,   0,   0,   NA,     0,  1)
-
-/* 16XX UART */
-MUX_CFG("R13_1610_UART1_TX",    A,  12,     6,   2,  10,   0,    2,    10,  1)
-MUX_CFG("V14_16XX_UART1_RX",    9,  18,     0,   2,   2,   0,    2,     2,  1)
-MUX_CFG("R14_1610_UART1_CTS",   9,  15,     0,   2,   1,   0,    2,     1,  1)
-MUX_CFG("AA15_1610_UART1_RTS",  9,  12,     1,   2,   0,   0,    2,     0,  1)
-MUX_CFG("R9_16XX_UART2_RX",     C,  18,     0,   3,   0,   0,    3,     0,  1)
-MUX_CFG("L14_16XX_UART3_RX",    6,   3,     0,   0,  31,   0,    0,    31,  1)
-
-/* I2C interface */
-MUX_CFG("I2C_SCL",              7,  24,     0,  NA,   0,   0,   NA,     0,  0)
-MUX_CFG("I2C_SDA",              7,  27,     0,  NA,   0,   0,   NA,     0,  0)
-
-/* Keypad */
-MUX_CFG("F18_1610_KBC0",        3,  15,     0,   0,   5,   1,    0,     0,  0)
-MUX_CFG("D20_1610_KBC1",        3,  12,     0,   0,   4,   1,    0,     0,  0)
-MUX_CFG("D19_1610_KBC2",        3,   9,     0,   0,   3,   1,    0,     0,  0)
-MUX_CFG("E18_1610_KBC3",        3,   6,     0,   0,   2,   1,    0,     0,  0)
-MUX_CFG("C21_1610_KBC4",        3,   3,     0,   0,   1,   1,    0,     0,  0)
-MUX_CFG("G18_1610_KBR0",        4,   0,     0,   0,   10,  1,    0,     1,  0)
-MUX_CFG("F19_1610_KBR1",        3,   27,    0,   0,   9,   1,    0,     1,  0)
-MUX_CFG("H14_1610_KBR2",        3,   24,    0,   0,   8,   1,    0,     1,  0)
-MUX_CFG("E20_1610_KBR3",        3,   21,    0,   0,   7,   1,    0,     1,  0)
-MUX_CFG("E19_1610_KBR4",        3,   18,    0,   0,   6,   1,    0,     1,  0)
-MUX_CFG("N19_1610_KBR5",        6,  12,     1,   1,   2,   1,    1,     1,  0)
-
-/* Power management */
-MUX_CFG("T20_1610_LOW_PWR",     7,   12,    1,   NA,   0,   0,   NA,    0,  0)
-
-/* MCLK Settings */
-MUX_CFG("V5_1710_MCLK_ON",      B,   15,    0,   NA,   0,   0,   NA,    0,  0)
-MUX_CFG("V5_1710_MCLK_OFF",     B,   15,    6,   NA,   0,   0,   NA,    0,  0)
-MUX_CFG("R10_1610_MCLK_ON",     B,   18,    0,   NA,  22,   0,   NA,    1,  0)
-MUX_CFG("R10_1610_MCLK_OFF",    B,   18,    6,   2,   22,   1,   2,     1,  1)
-
-/* CompactFlash controller, conflicts with MMC1 */
-MUX_CFG("P11_1610_CF_CD2",      A,   27,    3,   2,   15,   1,   2,     1,  1)
-MUX_CFG("R11_1610_CF_IOIS16",   B,    0,    3,   2,   16,   1,   2,     1,  1)
-MUX_CFG("V10_1610_CF_IREQ",     A,   24,    3,   2,   14,   0,   2,     0,  1)
-MUX_CFG("W10_1610_CF_RESET",    A,   18,    3,   2,   12,   1,   2,     1,  1)
-MUX_CFG("W11_1610_CF_CD1",     10,   15,    3,   3,    8,   1,   3,     1,  1)
-};
+       /* 24xx Menelaus interrupt */
+       W19_24XX_SYS_NIRQ,
 
-#endif /* __MUX_C__ */
+       /* 24xx GPIO */
+       Y20_24XX_GPIO60,
+       M15_24XX_GPIO92,
+};
 
 #ifdef CONFIG_OMAP_MUX
 /* setup pin muxing in Linux */
-extern int omap_cfg_reg(reg_cfg_t reg_cfg);
+extern int omap1_mux_init(void);
+extern int omap2_mux_init(void);
+extern int omap_mux_register(struct pin_config * pins, unsigned long size);
+extern int omap_cfg_reg(unsigned long reg_cfg);
 #else
 /* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
-static inline int omap_cfg_reg(reg_cfg_t reg_cfg) { return 0; }
+static inline int omap1_mux_init(void) { return 0; }
+static inline int omap2_mux_init(void) { return 0; }
+static inline int omap_cfg_reg(unsigned long reg_cfg) { return 0; }
 #endif
 
 #endif
index f086a39339060c1012036f0e68cbaf0120ad0fb9..c575d354850f459f1d8290f7074ba3dc2cb119f0 100644 (file)
@@ -25,8 +25,8 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef __ASM_ARCH_OMAP1510_H
-#define __ASM_ARCH_OMAP1510_H
+#ifndef __ASM_ARCH_OMAP15XX_H
+#define __ASM_ARCH_OMAP15XX_H
 
 /*
  * ----------------------------------------------------------------------------
@@ -44,5 +44,5 @@
 #define OMAP1510_DSPREG_SIZE   SZ_128K
 #define OMAP1510_DSPREG_START  0xE1000000
 
-#endif /*  __ASM_ARCH_OMAP1510_H */
+#endif /*  __ASM_ARCH_OMAP15XX_H */
 
index a9105466a4179d925d9dc80dca933579d5ca79ca..6e59805fa6545b8c3edeef8be3e2378b8fb0cf19 100644 (file)
@@ -1,15 +1,24 @@
 #ifndef __ASM_ARCH_OMAP24XX_H
 #define __ASM_ARCH_OMAP24XX_H
 
-#define OMAP24XX_L4_IO_BASE    0x48000000
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers. Note also that some of these defines are needed
+ * for omap1 to compile without adding ifdefs.
+ */
+
+#define L4_24XX_BASE           0x48000000
+#define L3_24XX_BASE           0x68000000
 
 /* interrupt controller */
-#define OMAP24XX_IC_BASE       (OMAP24XX_L4_IO_BASE + 0xfe000)
+#define OMAP24XX_IC_BASE       (L4_24XX_BASE + 0xfe000)
 #define VA_IC_BASE             IO_ADDRESS(OMAP24XX_IC_BASE)
-
 #define OMAP24XX_IVA_INTC_BASE 0x40000000
-
 #define IRQ_SIR_IRQ            0x0040
 
+#define OMAP24XX_32KSYNCT_BASE (L4_24XX_BASE + 0x4000)
+#define OMAP24XX_PRCM_BASE     (L4_24XX_BASE + 0x8000)
+#define OMAP24XX_SDRC_BASE     (L3_24XX_BASE + 0x9000)
+
 #endif /* __ASM_ARCH_OMAP24XX_H */
 
diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h
new file mode 100644 (file)
index 0000000..4ba2622
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * File: include/asm-arm/arch-omap/omapfb.h
+ *
+ * Framebuffer driver for TI OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@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.
+ */
+
+#ifndef __OMAPFB_H
+#define __OMAPFB_H
+
+/* IOCTL commands. */
+
+#define OMAP_IOW(num, dtype)   _IOW('O', num, dtype)
+#define OMAP_IOR(num, dtype)   _IOR('O', num, dtype)
+#define OMAP_IOWR(num, dtype)  _IOWR('O', num, dtype)
+#define OMAP_IO(num)           _IO('O', num)
+
+#define OMAPFB_MIRROR          OMAP_IOW(31, int)
+#define OMAPFB_SYNC_GFX                OMAP_IO(37)
+#define OMAPFB_VSYNC           OMAP_IO(38)
+#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, enum omapfb_update_mode)
+#define OMAPFB_GET_CAPS                OMAP_IOR(42, unsigned long)
+#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, enum omapfb_update_mode)
+#define OMAPFB_LCD_TEST                OMAP_IOW(45, int)
+#define OMAPFB_CTRL_TEST       OMAP_IOW(46, int)
+#define OMAPFB_UPDATE_WINDOW   OMAP_IOW(47, struct omapfb_update_window)
+#define OMAPFB_SETUP_PLANE     OMAP_IOW(48, struct omapfb_setup_plane)
+#define OMAPFB_ENABLE_PLANE    OMAP_IOW(49, struct omapfb_enable_plane)
+#define OMAPFB_SET_COLOR_KEY   OMAP_IOW(50, struct omapfb_color_key)
+
+#define OMAPFB_CAPS_GENERIC_MASK       0x00000fff
+#define OMAPFB_CAPS_LCDC_MASK          0x00fff000
+#define OMAPFB_CAPS_PANEL_MASK         0xff000000
+
+#define OMAPFB_CAPS_MANUAL_UPDATE      0x00001000
+#define OMAPFB_CAPS_SET_BACKLIGHT      0x01000000
+
+/* Values from DSP must map to lower 16-bits */
+#define OMAPFB_FORMAT_MASK         0x00ff
+#define OMAPFB_FORMAT_FLAG_DOUBLE  0x0100
+
+enum omapfb_color_format {
+       OMAPFB_COLOR_RGB565 = 0,
+       OMAPFB_COLOR_YUV422,
+       OMAPFB_COLOR_YUV420,
+       OMAPFB_COLOR_CLUT_8BPP,
+       OMAPFB_COLOR_CLUT_4BPP,
+       OMAPFB_COLOR_CLUT_2BPP,
+       OMAPFB_COLOR_CLUT_1BPP,
+};
+
+struct omapfb_update_window {
+       u32 x, y;
+       u32 width, height;
+       u32 format;
+};
+
+enum omapfb_plane {
+       OMAPFB_PLANE_GFX = 0,
+       OMAPFB_PLANE_VID1,
+       OMAPFB_PLANE_VID2,
+};
+
+enum omapfb_channel_out {
+       OMAPFB_CHANNEL_OUT_LCD = 0,
+       OMAPFB_CHANNEL_OUT_DIGIT,
+};
+
+struct omapfb_setup_plane {
+       u8  plane;
+       u8  channel_out;
+       u32 offset;
+       u32 pos_x, pos_y;
+       u32 width, height;
+       u32 color_mode;
+};
+
+struct omapfb_enable_plane {
+       u8  plane;
+       u8  enable;
+};
+
+enum omapfb_color_key_type {
+       OMAPFB_COLOR_KEY_DISABLED = 0,
+       OMAPFB_COLOR_KEY_GFX_DST,
+       OMAPFB_COLOR_KEY_VID_SRC,
+};
+
+struct omapfb_color_key {
+       u8  channel_out;
+       u32 background;
+       u32 trans_key;
+       u8  key_type;
+};
+
+enum omapfb_update_mode {
+       OMAPFB_UPDATE_DISABLED = 0,
+       OMAPFB_AUTO_UPDATE,
+       OMAPFB_MANUAL_UPDATE
+};
+
+#ifdef __KERNEL__
+
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+
+#define OMAP_LCDC_INV_VSYNC             0x0001
+#define OMAP_LCDC_INV_HSYNC             0x0002
+#define OMAP_LCDC_INV_PIX_CLOCK         0x0004
+#define OMAP_LCDC_INV_OUTPUT_EN         0x0008
+#define OMAP_LCDC_HSVS_RISING_EDGE      0x0010
+#define OMAP_LCDC_HSVS_OPPOSITE         0x0020
+
+#define OMAP_LCDC_SIGNAL_MASK          0x003f
+
+#define OMAP_LCDC_PANEL_TFT            0x0100
+
+#ifdef CONFIG_ARCH_OMAP1
+#define OMAPFB_PLANE_NUM               1
+#else
+#define OMAPFB_PLANE_NUM               3
+#endif
+
+struct omapfb_device;
+
+struct lcd_panel {
+       const char      *name;
+       int             config;         /* TFT/STN, signal inversion */
+       int             bpp;            /* Pixel format in fb mem */
+       int             data_lines;     /* Lines on LCD HW interface */
+
+       int             x_res, y_res;
+       int             pixel_clock;    /* In kHz */
+       int             hsw;            /* Horizontal synchronization
+                                          pulse width */
+       int             hfp;            /* Horizontal front porch */
+       int             hbp;            /* Horizontal back porch */
+       int             vsw;            /* Vertical synchronization
+                                          pulse width */
+       int             vfp;            /* Vertical front porch */
+       int             vbp;            /* Vertical back porch */
+       int             acb;            /* ac-bias pin frequency */
+       int             pcd;            /* pixel clock divider.
+                                          Obsolete use pixel_clock instead */
+
+       int             (*init)         (struct omapfb_device *fbdev);
+       void            (*cleanup)      (void);
+       int             (*enable)       (void);
+       void            (*disable)      (void);
+       unsigned long   (*get_caps)     (void);
+       int             (*set_bklight_level)(unsigned int level);
+       unsigned int    (*get_bklight_level)(void);
+       unsigned int    (*get_bklight_max)  (void);
+       int             (*run_test)     (int test_num);
+};
+
+struct omapfb_device;
+
+struct extif_timings {
+       int cs_on_time;
+       int cs_off_time;
+       int we_on_time;
+       int we_off_time;
+       int re_on_time;
+       int re_off_time;
+       int we_cycle_time;
+       int re_cycle_time;
+       int cs_pulse_width;
+       int access_time;
+};
+
+struct lcd_ctrl_extif {
+       int  (*init)            (void);
+       void (*cleanup)         (void);
+       void (*set_timings)     (const struct extif_timings *timings);
+       void (*write_command)   (u32 cmd);
+       u32  (*read_data)       (void);
+       void (*write_data)      (u32 data);
+       void (*transfer_area)   (int width, int height,
+                                void (callback)(void * data), void *data);
+};
+
+struct lcd_ctrl {
+       const char      *name;
+       void            *data;
+
+       int             (*init)           (struct omapfb_device *fbdev,
+                                          int ext_mode, int req_vram_size);
+       void            (*cleanup)        (void);
+       void            (*get_vram_layout)(unsigned long *size,
+                                          void **virt_base,
+                                          dma_addr_t *phys_base);
+       unsigned long   (*get_caps)       (void);
+       int             (*set_update_mode)(enum omapfb_update_mode mode);
+       enum omapfb_update_mode (*get_update_mode)(void);
+       int             (*setup_plane)    (int plane, int channel_out,
+                                          unsigned long offset,
+                                          int screen_width,
+                                          int pos_x, int pos_y, int width,
+                                          int height, int color_mode);
+       int             (*enable_plane)   (int plane, int enable);
+       int             (*update_window)  (struct omapfb_update_window *win,
+                                          void (*callback)(void *),
+                                          void *callback_data);
+       void            (*sync)           (void);
+       void            (*suspend)        (void);
+       void            (*resume)         (void);
+       int             (*run_test)       (int test_num);
+       int             (*setcolreg)      (u_int regno, u16 red, u16 green,
+                                          u16 blue, u16 transp,
+                                          int update_hw_mem);
+       int             (*set_color_key)  (struct omapfb_color_key *ck);
+
+};
+
+enum omapfb_state {
+       OMAPFB_DISABLED = 0,
+       OMAPFB_SUSPENDED= 99,
+       OMAPFB_ACTIVE   = 100
+};
+
+struct omapfb_device {
+       int                     state;
+       int                     ext_lcdc;               /* Using external
+                                                           LCD controller */
+       struct semaphore        rqueue_sema;
+
+       void                    *vram_virt_base;
+       dma_addr_t              vram_phys_base;
+       unsigned long           vram_size;
+
+       int                     color_mode;
+       int                     palette_size;
+       int                     mirror;
+       u32                     pseudo_palette[17];
+
+       struct lcd_panel        *panel;                 /* LCD panel */
+       struct lcd_ctrl         *ctrl;                  /* LCD controller */
+       struct lcd_ctrl         *int_ctrl;              /* internal LCD ctrl */
+       struct lcd_ctrl_extif   *ext_if;                /* LCD ctrl external
+                                                          interface */
+       struct fb_info          *fb_info;
+
+       struct device           *dev;
+};
+
+extern struct lcd_panel h3_panel;
+extern struct lcd_panel h2_panel;
+extern struct lcd_panel p2_panel;
+extern struct lcd_panel osk_panel;
+extern struct lcd_panel innovator1610_panel;
+extern struct lcd_panel innovator1510_panel;
+
+#ifdef CONFIG_ARCH_OMAP1
+extern struct lcd_ctrl omap1_lcd_ctrl;
+#else
+extern struct lcd_ctrl omap2_disp_ctrl;
+#endif
+
+extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+
+#endif /* __KERNEL__ */
+
+#endif /* __OMAPFB_H */
index fbd742d0c49997fc46e5ddc1299dd9d399242389..7c790425e3633527080d98c238389ca0d1afbd01 100644 (file)
 #define OMAP1610_IDLECT3               0xfffece24
 #define OMAP1610_IDLE_LOOP_REQUEST     0x0400
 
-#if     !defined(CONFIG_ARCH_OMAP1510) && \
+#define OMAP730_IDLECT1_SLEEP_VAL      0x16c7
+#define OMAP730_IDLECT2_SLEEP_VAL      0x09c7
+#define OMAP730_IDLECT3_VAL            0x3f
+#define OMAP730_IDLECT3                0xfffece24
+#define OMAP730_IDLE_LOOP_REQUEST      0x0C00
+
+#if     !defined(CONFIG_ARCH_OMAP730) && \
+       !defined(CONFIG_ARCH_OMAP15XX) && \
        !defined(CONFIG_ARCH_OMAP16XX) && \
        !defined(CONFIG_ARCH_OMAP24XX)
 #error "Power management for this processor not implemented yet"
 #ifndef __ASSEMBLER__
 extern void omap_pm_idle(void);
 extern void omap_pm_suspend(void);
+extern void omap730_cpu_suspend(unsigned short, unsigned short);
 extern void omap1510_cpu_suspend(unsigned short, unsigned short);
 extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap730_idle_loop_suspend(void);
 extern void omap1510_idle_loop_suspend(void);
 extern void omap1610_idle_loop_suspend(void);
 
@@ -118,6 +127,8 @@ extern void omap_serial_wake_trigger(int enable);
 #define omap_serial_wake_trigger(x)    {}
 #endif /* CONFIG_OMAP_SERIAL_WAKE */
 
+extern unsigned int omap730_cpu_suspend_sz;
+extern unsigned int omap730_idle_loop_suspend_sz;
 extern unsigned int omap1510_cpu_suspend_sz;
 extern unsigned int omap1510_idle_loop_suspend_sz;
 extern unsigned int omap1610_cpu_suspend_sz;
@@ -131,6 +142,10 @@ extern unsigned int omap1610_idle_loop_suspend_sz;
 #define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
 #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
 
+#define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x))
+#define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]
+
 #define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x)
 #define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x))
 #define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]
@@ -188,13 +203,34 @@ enum mpui1510_save_state {
        MPUI1510_SLEEP_SAVE_EMIFS_CONFIG,
        MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR,
        MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR,
-#if defined(CONFIG_ARCH_OMAP1510)
+#if defined(CONFIG_ARCH_OMAP15XX)
        MPUI1510_SLEEP_SAVE_SIZE
 #else
        MPUI1510_SLEEP_SAVE_SIZE = 0
 #endif
 };
 
+enum mpui730_save_state {
+       MPUI730_SLEEP_SAVE_START = 0,
+       /*
+        * MPUI registers 32 bits
+        */
+       MPUI730_SLEEP_SAVE_MPUI_CTRL,
+       MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+       MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+       MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS,
+       MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+       MPUI730_SLEEP_SAVE_EMIFS_CONFIG,
+       MPUI730_SLEEP_SAVE_OMAP_IH1_MIR,
+       MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR,
+       MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR,
+#if defined(CONFIG_ARCH_OMAP730)
+       MPUI730_SLEEP_SAVE_SIZE
+#else
+       MPUI730_SLEEP_SAVE_SIZE = 0
+#endif
+};
+
 enum mpui1610_save_state {
        MPUI1610_SLEEP_SAVE_START = 0,
        /*
diff --git a/include/asm-arm/arch-omap/prcm.h b/include/asm-arm/arch-omap/prcm.h
new file mode 100644 (file)
index 0000000..7b48a5c
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * prcm.h - Access definations for use in OMAP24XX clock and power management
+ *
+ * Copyright (C) 2005 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
+ */
+
+#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
+#define __ASM_ARM_ARCH_DPM_PRCM_H
+
+/* SET_PERFORMANCE_LEVEL PARAMETERS */
+#define PRCM_HALF_SPEED 1
+#define PRCM_FULL_SPEED 2
+
+#ifndef __ASSEMBLER__
+
+#define PRCM_REG32(offset)     __REG32(OMAP24XX_PRCM_BASE + (offset))
+
+#define PRCM_REVISION          PRCM_REG32(0x000)
+#define PRCM_SYSCONFIG         PRCM_REG32(0x010)
+#define PRCM_IRQSTATUS_MPU     PRCM_REG32(0x018)
+#define PRCM_IRQENABLE_MPU     PRCM_REG32(0x01C)
+#define PRCM_VOLTCTRL          PRCM_REG32(0x050)
+#define PRCM_VOLTST            PRCM_REG32(0x054)
+#define PRCM_CLKSRC_CTRL       PRCM_REG32(0x060)
+#define PRCM_CLKOUT_CTRL       PRCM_REG32(0x070)
+#define PRCM_CLKEMUL_CTRL      PRCM_REG32(0x078)
+#define PRCM_CLKCFG_CTRL       PRCM_REG32(0x080)
+#define PRCM_CLKCFG_STATUS     PRCM_REG32(0x084)
+#define PRCM_VOLTSETUP         PRCM_REG32(0x090)
+#define PRCM_CLKSSETUP         PRCM_REG32(0x094)
+#define PRCM_POLCTRL           PRCM_REG32(0x098)
+
+/* GENERAL PURPOSE */
+#define GENERAL_PURPOSE1       PRCM_REG32(0x0B0)
+#define GENERAL_PURPOSE2       PRCM_REG32(0x0B4)
+#define GENERAL_PURPOSE3       PRCM_REG32(0x0B8)
+#define GENERAL_PURPOSE4       PRCM_REG32(0x0BC)
+#define GENERAL_PURPOSE5       PRCM_REG32(0x0C0)
+#define GENERAL_PURPOSE6       PRCM_REG32(0x0C4)
+#define GENERAL_PURPOSE7       PRCM_REG32(0x0C8)
+#define GENERAL_PURPOSE8       PRCM_REG32(0x0CC)
+#define GENERAL_PURPOSE9       PRCM_REG32(0x0D0)
+#define GENERAL_PURPOSE10      PRCM_REG32(0x0D4)
+#define GENERAL_PURPOSE11      PRCM_REG32(0x0D8)
+#define GENERAL_PURPOSE12      PRCM_REG32(0x0DC)
+#define GENERAL_PURPOSE13      PRCM_REG32(0x0E0)
+#define GENERAL_PURPOSE14      PRCM_REG32(0x0E4)
+#define GENERAL_PURPOSE15      PRCM_REG32(0x0E8)
+#define GENERAL_PURPOSE16      PRCM_REG32(0x0EC)
+#define GENERAL_PURPOSE17      PRCM_REG32(0x0F0)
+#define GENERAL_PURPOSE18      PRCM_REG32(0x0F4)
+#define GENERAL_PURPOSE19      PRCM_REG32(0x0F8)
+#define GENERAL_PURPOSE20      PRCM_REG32(0x0FC)
+
+/* MPU */
+#define CM_CLKSEL_MPU          PRCM_REG32(0x140)
+#define CM_CLKSTCTRL_MPU       PRCM_REG32(0x148)
+#define RM_RSTST_MPU           PRCM_REG32(0x158)
+#define PM_WKDEP_MPU           PRCM_REG32(0x1C8)
+#define PM_EVGENCTRL_MPU       PRCM_REG32(0x1D4)
+#define PM_EVEGENONTIM_MPU     PRCM_REG32(0x1D8)
+#define PM_EVEGENOFFTIM_MPU    PRCM_REG32(0x1DC)
+#define PM_PWSTCTRL_MPU                PRCM_REG32(0x1E0)
+#define PM_PWSTST_MPU          PRCM_REG32(0x1E4)
+
+/* CORE */
+#define CM_FCLKEN1_CORE                PRCM_REG32(0x200)
+#define CM_FCLKEN2_CORE                PRCM_REG32(0x204)
+#define CM_FCLKEN3_CORE                PRCM_REG32(0x208)
+#define CM_ICLKEN1_CORE                PRCM_REG32(0x210)
+#define CM_ICLKEN2_CORE                PRCM_REG32(0x214)
+#define CM_ICLKEN3_CORE                PRCM_REG32(0x218)
+#define CM_ICLKEN4_CORE                PRCM_REG32(0x21C)
+#define CM_IDLEST1_CORE                PRCM_REG32(0x220)
+#define CM_IDLEST2_CORE                PRCM_REG32(0x224)
+#define CM_IDLEST3_CORE                PRCM_REG32(0x228)
+#define CM_IDLEST4_CORE                PRCM_REG32(0x22C)
+#define CM_AUTOIDLE1_CORE      PRCM_REG32(0x230)
+#define CM_AUTOIDLE2_CORE      PRCM_REG32(0x234)
+#define CM_AUTOIDLE3_CORE      PRCM_REG32(0x238)
+#define CM_AUTOIDLE4_CORE      PRCM_REG32(0x23C)
+#define CM_CLKSEL1_CORE                PRCM_REG32(0x240)
+#define CM_CLKSEL2_CORE                PRCM_REG32(0x244)
+#define CM_CLKSTCTRL_CORE      PRCM_REG32(0x248)
+#define PM_WKEN1_CORE          PRCM_REG32(0x2A0)
+#define PM_WKEN2_CORE          PRCM_REG32(0x2A4)
+#define PM_WKST1_CORE          PRCM_REG32(0x2B0)
+#define PM_WKST2_CORE          PRCM_REG32(0x2B4)
+#define PM_WKDEP_CORE          PRCM_REG32(0x2C8)
+#define PM_PWSTCTRL_CORE       PRCM_REG32(0x2E0)
+#define PM_PWSTST_CORE         PRCM_REG32(0x2E4)
+
+/* GFX */
+#define CM_FCLKEN_GFX          PRCM_REG32(0x300)
+#define CM_ICLKEN_GFX          PRCM_REG32(0x310)
+#define CM_IDLEST_GFX          PRCM_REG32(0x320)
+#define CM_CLKSEL_GFX          PRCM_REG32(0x340)
+#define CM_CLKSTCTRL_GFX       PRCM_REG32(0x348)
+#define RM_RSTCTRL_GFX         PRCM_REG32(0x350)
+#define RM_RSTST_GFX           PRCM_REG32(0x358)
+#define PM_WKDEP_GFX           PRCM_REG32(0x3C8)
+#define PM_PWSTCTRL_GFX                PRCM_REG32(0x3E0)
+#define PM_PWSTST_GFX          PRCM_REG32(0x3E4)
+
+/* WAKE-UP */
+#define CM_FCLKEN_WKUP         PRCM_REG32(0x400)
+#define CM_ICLKEN_WKUP         PRCM_REG32(0x410)
+#define CM_IDLEST_WKUP         PRCM_REG32(0x420)
+#define CM_AUTOIDLE_WKUP       PRCM_REG32(0x430)
+#define CM_CLKSEL_WKUP         PRCM_REG32(0x440)
+#define RM_RSTCTRL_WKUP                PRCM_REG32(0x450)
+#define RM_RSTTIME_WKUP                PRCM_REG32(0x454)
+#define RM_RSTST_WKUP          PRCM_REG32(0x458)
+#define PM_WKEN_WKUP           PRCM_REG32(0x4A0)
+#define PM_WKST_WKUP           PRCM_REG32(0x4B0)
+
+/* CLOCKS */
+#define CM_CLKEN_PLL           PRCM_REG32(0x500)
+#define CM_IDLEST_CKGEN                PRCM_REG32(0x520)
+#define CM_AUTOIDLE_PLL                PRCM_REG32(0x530)
+#define CM_CLKSEL1_PLL         PRCM_REG32(0x540)
+#define CM_CLKSEL2_PLL         PRCM_REG32(0x544)
+
+/* DSP */
+#define CM_FCLKEN_DSP          PRCM_REG32(0x800)
+#define CM_ICLKEN_DSP          PRCM_REG32(0x810)
+#define CM_IDLEST_DSP          PRCM_REG32(0x820)
+#define CM_AUTOIDLE_DSP                PRCM_REG32(0x830)
+#define CM_CLKSEL_DSP          PRCM_REG32(0x840)
+#define CM_CLKSTCTRL_DSP       PRCM_REG32(0x848)
+#define RM_RSTCTRL_DSP         PRCM_REG32(0x850)
+#define RM_RSTST_DSP           PRCM_REG32(0x858)
+#define PM_WKEN_DSP            PRCM_REG32(0x8A0)
+#define PM_WKDEP_DSP           PRCM_REG32(0x8C8)
+#define PM_PWSTCTRL_DSP                PRCM_REG32(0x8E0)
+#define PM_PWSTST_DSP          PRCM_REG32(0x8E4)
+#define PRCM_IRQSTATUS_DSP     PRCM_REG32(0x8F0)
+#define PRCM_IRQENABLE_DSP     PRCM_REG32(0x8F4)
+
+/* IVA */
+#define PRCM_IRQSTATUS_IVA     PRCM_REG32(0x8F8)
+#define PRCM_IRQENABLE_IVA     PRCM_REG32(0x8FC)
+
+/* Modem on 2430 */
+#define CM_FCLKEN_MDM          PRCM_REG32(0xC00)
+#define CM_ICLKEN_MDM          PRCM_REG32(0xC10)
+#define CM_IDLEST_MDM          PRCM_REG32(0xC20)
+#define CM_CLKSEL_MDM          PRCM_REG32(0xC40)
+
+/* FIXME: Move to header for 2430 */
+#define DISP_BASE              (OMAP24XX_L4_IO_BASE+0x50000)
+#define DISP_REG32(offset)     __REG32(DISP_BASE + (offset))
+
+#define OMAP24XX_GPMC_BASE     (L3_24XX_BASE + 0xa000)
+#define GPMC_BASE              (OMAP24XX_GPMC_BASE)
+#define GPMC_REG32(offset)     __REG32(GPMC_BASE + (offset))
+
+#define GPT1_BASE              (OMAP24XX_GPT1)
+#define GPT1_REG32(offset)     __REG32(GPT1_BASE + (offset))
+
+/* Misc sysconfig */
+#define DISPC_SYSCONFIG                DISP_REG32(0x410)
+#define SPI_BASE               (OMAP24XX_L4_IO_BASE+0x98000)
+#define MCSPI1_SYSCONFIG       __REG32(SPI_BASE + 0x10)
+#define MCSPI2_SYSCONFIG       __REG32(SPI_BASE+0x2000 + 0x10)
+
+//#define DSP_MMU_SYSCONFIG    0x5A000010
+#define CAMERA_MMU_SYSCONFIG   __REG32(DISP_BASE+0x2C10)
+//#define IVA_MMU_SYSCONFIG    0x5D000010
+//#define DSP_DMA_SYSCONFIG    0x00FCC02C
+#define CAMERA_DMA_SYSCONFIG   __REG32(DISP_BASE+0x282C)
+#define SYSTEM_DMA_SYSCONFIG   __REG32(DISP_BASE+0x602C)
+#define GPMC_SYSCONFIG         GPMC_REG32(0x010)
+#define MAILBOXES_SYSCONFIG    __REG32(OMAP24XX_L4_IO_BASE+0x94010)
+#define UART1_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
+#define UART2_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
+#define UART3_SYSCONFIG                __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
+//#define IVA_SYSCONFIG                0x5C060010
+#define SDRC_SYSCONFIG         __REG32(OMAP24XX_SDRC_BASE+0x10)
+#define SMS_SYSCONFIG          __REG32(OMAP24XX_SMS_BASE+0x10)
+#define SSI_SYSCONFIG          __REG32(DISP_BASE+0x8010)
+//#define VLYNQ_SYSCONFIG      0x67FFFE10
+
+/* rkw - good cannidates for PM_ to start what nm was trying */
+#define OMAP24XX_GPT2          (OMAP24XX_L4_IO_BASE+0x2A000)
+#define OMAP24XX_GPT3          (OMAP24XX_L4_IO_BASE+0x78000)
+#define OMAP24XX_GPT4          (OMAP24XX_L4_IO_BASE+0x7A000)
+#define OMAP24XX_GPT5          (OMAP24XX_L4_IO_BASE+0x7C000)
+#define OMAP24XX_GPT6          (OMAP24XX_L4_IO_BASE+0x7E000)
+#define OMAP24XX_GPT7          (OMAP24XX_L4_IO_BASE+0x80000)
+#define OMAP24XX_GPT8          (OMAP24XX_L4_IO_BASE+0x82000)
+#define OMAP24XX_GPT9          (OMAP24XX_L4_IO_BASE+0x84000)
+#define OMAP24XX_GPT10         (OMAP24XX_L4_IO_BASE+0x86000)
+#define OMAP24XX_GPT11         (OMAP24XX_L4_IO_BASE+0x88000)
+#define OMAP24XX_GPT12         (OMAP24XX_L4_IO_BASE+0x8A000)
+
+#define GPTIMER1_SYSCONFIG     GPT1_REG32(0x010)
+#define GPTIMER2_SYSCONFIG     __REG32(OMAP24XX_GPT2 + 0x10)
+#define GPTIMER3_SYSCONFIG     __REG32(OMAP24XX_GPT3 + 0x10)
+#define GPTIMER4_SYSCONFIG     __REG32(OMAP24XX_GPT4 + 0x10)
+#define GPTIMER5_SYSCONFIG     __REG32(OMAP24XX_GPT5 + 0x10)
+#define GPTIMER6_SYSCONFIG     __REG32(OMAP24XX_GPT6 + 0x10)
+#define GPTIMER7_SYSCONFIG     __REG32(OMAP24XX_GPT7 + 0x10)
+#define GPTIMER8_SYSCONFIG     __REG32(OMAP24XX_GPT8 + 0x10)
+#define GPTIMER9_SYSCONFIG     __REG32(OMAP24XX_GPT9 + 0x10)
+#define GPTIMER10_SYSCONFIG    __REG32(OMAP24XX_GPT10 + 0x10)
+#define GPTIMER11_SYSCONFIG    __REG32(OMAP24XX_GPT11 + 0x10)
+#define GPTIMER12_SYSCONFIG    __REG32(OMAP24XX_GPT12 + 0x10)
+
+#define GPIOX_BASE(X)          (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+
+#define GPIO1_SYSCONFIG                __REG32((GPIOX_BASE(1)+0x10))
+#define GPIO2_SYSCONFIG                __REG32((GPIOX_BASE(2)+0x10))
+#define GPIO3_SYSCONFIG                __REG32((GPIOX_BASE(3)+0x10))
+#define GPIO4_SYSCONFIG                __REG32((GPIOX_BASE(4)+0x10))
+
+/* GP TIMER 1 */
+#define GPTIMER1_TISTAT                GPT1_REG32(0x014)
+#define GPTIMER1_TISR          GPT1_REG32(0x018)
+#define GPTIMER1_TIER          GPT1_REG32(0x01C)
+#define GPTIMER1_TWER          GPT1_REG32(0x020)
+#define GPTIMER1_TCLR          GPT1_REG32(0x024)
+#define GPTIMER1_TCRR          GPT1_REG32(0x028)
+#define GPTIMER1_TLDR          GPT1_REG32(0x02C)
+#define GPTIMER1_TTGR          GPT1_REG32(0x030)
+#define GPTIMER1_TWPS          GPT1_REG32(0x034)
+#define GPTIMER1_TMAR          GPT1_REG32(0x038)
+#define GPTIMER1_TCAR1         GPT1_REG32(0x03C)
+#define GPTIMER1_TSICR         GPT1_REG32(0x040)
+#define GPTIMER1_TCAR2         GPT1_REG32(0x044)
+
+/* rkw -- base fix up please... */
+#define GPTIMER3_TISR          __REG32(OMAP24XX_L4_IO_BASE+0x78018)
+
+/* SDRC */
+#define SDRC_DLLA_CTRL         __REG32(OMAP24XX_SDRC_BASE+0x060)
+#define SDRC_DLLA_STATUS       __REG32(OMAP24XX_SDRC_BASE+0x064)
+#define SDRC_DLLB_CTRL         __REG32(OMAP24XX_SDRC_BASE+0x068)
+#define SDRC_DLLB_STATUS       __REG32(OMAP24XX_SDRC_BASE+0x06C)
+#define SDRC_POWER             __REG32(OMAP24XX_SDRC_BASE+0x070)
+#define SDRC_MR_0              __REG32(OMAP24XX_SDRC_BASE+0x084)
+
+/* GPIO 1 */
+#define GPIO1_BASE             GPIOX_BASE(1)
+#define GPIO1_REG32(offset)    __REG32(GPIO1_BASE + (offset))
+#define GPIO1_IRQENABLE1       GPIO1_REG32(0x01C)
+#define GPIO1_IRQSTATUS1       GPIO1_REG32(0x018)
+#define GPIO1_IRQENABLE2       GPIO1_REG32(0x02C)
+#define GPIO1_IRQSTATUS2       GPIO1_REG32(0x028)
+#define GPIO1_WAKEUPENABLE     GPIO1_REG32(0x020)
+#define GPIO1_RISINGDETECT     GPIO1_REG32(0x048)
+#define GPIO1_DATAIN           GPIO1_REG32(0x038)
+#define GPIO1_OE               GPIO1_REG32(0x034)
+#define GPIO1_DATAOUT          GPIO1_REG32(0x03C)
+
+/* GPIO2 */
+#define GPIO2_BASE             GPIOX_BASE(2)
+#define GPIO2_REG32(offset)    __REG32(GPIO2_BASE + (offset))
+#define GPIO2_IRQENABLE1       GPIO2_REG32(0x01C)
+#define GPIO2_IRQSTATUS1       GPIO2_REG32(0x018)
+#define GPIO2_IRQENABLE2       GPIO2_REG32(0x02C)
+#define GPIO2_IRQSTATUS2       GPIO2_REG32(0x028)
+#define GPIO2_WAKEUPENABLE     GPIO2_REG32(0x020)
+#define GPIO2_RISINGDETECT     GPIO2_REG32(0x048)
+#define GPIO2_DATAIN           GPIO2_REG32(0x038)
+#define GPIO2_OE               GPIO2_REG32(0x034)
+#define GPIO2_DATAOUT          GPIO2_REG32(0x03C)
+
+/* GPIO 3 */
+#define GPIO3_BASE             GPIOX_BASE(3)
+#define GPIO3_REG32(offset)    __REG32(GPIO3_BASE + (offset))
+#define GPIO3_IRQENABLE1       GPIO3_REG32(0x01C)
+#define GPIO3_IRQSTATUS1       GPIO3_REG32(0x018)
+#define GPIO3_IRQENABLE2       GPIO3_REG32(0x02C)
+#define GPIO3_IRQSTATUS2       GPIO3_REG32(0x028)
+#define GPIO3_WAKEUPENABLE     GPIO3_REG32(0x020)
+#define GPIO3_RISINGDETECT     GPIO3_REG32(0x048)
+#define GPIO3_FALLINGDETECT    GPIO3_REG32(0x04C)
+#define GPIO3_DATAIN           GPIO3_REG32(0x038)
+#define GPIO3_OE               GPIO3_REG32(0x034)
+#define GPIO3_DATAOUT          GPIO3_REG32(0x03C)
+#define GPIO3_DEBOUNCENABLE    GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME   GPIO3_REG32(0x054)
+
+/* GPIO 4 */
+#define GPIO4_BASE             GPIOX_BASE(4)
+#define GPIO4_REG32(offset)    __REG32(GPIO4_BASE + (offset))
+#define GPIO4_IRQENABLE1       GPIO4_REG32(0x01C)
+#define GPIO4_IRQSTATUS1       GPIO4_REG32(0x018)
+#define GPIO4_IRQENABLE2       GPIO4_REG32(0x02C)
+#define GPIO4_IRQSTATUS2       GPIO4_REG32(0x028)
+#define GPIO4_WAKEUPENABLE     GPIO4_REG32(0x020)
+#define GPIO4_RISINGDETECT     GPIO4_REG32(0x048)
+#define GPIO4_FALLINGDETECT    GPIO4_REG32(0x04C)
+#define GPIO4_DATAIN           GPIO4_REG32(0x038)
+#define GPIO4_OE               GPIO4_REG32(0x034)
+#define GPIO4_DATAOUT          GPIO4_REG32(0x03C)
+#define GPIO4_DEBOUNCENABLE    GPIO4_REG32(0x050)
+#define GPIO4_DEBOUNCINGTIME   GPIO4_REG32(0x054)
+
+
+/* IO CONFIG */
+#define CONTROL_BASE           (OMAP24XX_CTRL_BASE)
+#define CONTROL_REG32(offset)  __REG32(CONTROL_BASE + (offset))
+
+#define CONTROL_PADCONF_SPI1_NCS2      CONTROL_REG32(0x104)
+#define CONTROL_PADCONF_SYS_XTALOUT    CONTROL_REG32(0x134)
+#define CONTROL_PADCONF_UART1_RX       CONTROL_REG32(0x0C8)
+#define CONTROL_PADCONF_MCBSP1_DX      CONTROL_REG32(0x10C)
+#define CONTROL_PADCONF_GPMC_NCS4      CONTROL_REG32(0x090)
+#define CONTROL_PADCONF_DSS_D5         CONTROL_REG32(0x0B8)
+#define CONTROL_PADCONF_DSS_D9         CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D13                CONTROL_REG32(0x0C0)
+#define CONTROL_PADCONF_DSS_VSYNC      CONTROL_REG32(0x0CC)
+
+/* CONTROL */
+#define CONTROL_DEVCONF                CONTROL_REG32(0x274)
+
+/* INTERRUPT CONTROLLER */
+#define INTC_BASE              (OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_REG32(offset)     __REG32(INTC_BASE + (offset))
+
+#define INTC1_U_BASE           INTC_REG32(0x000)
+#define INTC_MIR0              INTC_REG32(0x084)
+#define INTC_MIR_SET0          INTC_REG32(0x08C)
+#define INTC_MIR_CLEAR0                INTC_REG32(0x088)
+#define INTC_ISR_CLEAR0                INTC_REG32(0x094)
+#define INTC_MIR1              INTC_REG32(0x0A4)
+#define INTC_MIR_SET1          INTC_REG32(0x0AC)
+#define INTC_MIR_CLEAR1                INTC_REG32(0x0A8)
+#define INTC_ISR_CLEAR1                INTC_REG32(0x0B4)
+#define INTC_MIR2              INTC_REG32(0x0C4)
+#define INTC_MIR_SET2          INTC_REG32(0x0CC)
+#define INTC_MIR_CLEAR2                INTC_REG32(0x0C8)
+#define INTC_ISR_CLEAR2                INTC_REG32(0x0D4)
+#define INTC_SIR_IRQ           INTC_REG32(0x040)
+#define INTC_CONTROL           INTC_REG32(0x048)
+#define INTC_ILR11             INTC_REG32(0x12C)
+#define INTC_ILR32             INTC_REG32(0x180)
+#define INTC_ILR37             INTC_REG32(0x194)
+#define INTC_SYSCONFIG         INTC_REG32(0x010)
+
+/* RAM FIREWALL */
+#define RAMFW_BASE             (0x68005000)
+#define RAMFW_REG32(offset)    __REG32(RAMFW_BASE + (offset))
+
+#define RAMFW_REQINFOPERM0     RAMFW_REG32(0x048)
+#define RAMFW_READPERM0                RAMFW_REG32(0x050)
+#define RAMFW_WRITEPERM0       RAMFW_REG32(0x058)
+
+/* GPMC CS1 FPGA ON USER INTERFACE MODULE */
+//#define DEBUG_BOARD_LED_REGISTER 0x04000014
+
+/* GPMC CS0 */
+#define GPMC_CONFIG1_0         GPMC_REG32(0x060)
+#define GPMC_CONFIG2_0         GPMC_REG32(0x064)
+#define GPMC_CONFIG3_0         GPMC_REG32(0x068)
+#define GPMC_CONFIG4_0         GPMC_REG32(0x06C)
+#define GPMC_CONFIG5_0         GPMC_REG32(0x070)
+#define GPMC_CONFIG6_0         GPMC_REG32(0x074)
+#define GPMC_CONFIG7_0         GPMC_REG32(0x078)
+
+/* GPMC CS1 */
+#define GPMC_CONFIG1_1         GPMC_REG32(0x090)
+#define GPMC_CONFIG2_1         GPMC_REG32(0x094)
+#define GPMC_CONFIG3_1         GPMC_REG32(0x098)
+#define GPMC_CONFIG4_1         GPMC_REG32(0x09C)
+#define GPMC_CONFIG5_1         GPMC_REG32(0x0a0)
+#define GPMC_CONFIG6_1         GPMC_REG32(0x0a4)
+#define GPMC_CONFIG7_1         GPMC_REG32(0x0a8)
+
+/* DSS */
+#define DSS_CONTROL            DISP_REG32(0x040)
+#define DISPC_CONTROL          DISP_REG32(0x440)
+#define DISPC_SYSSTATUS                DISP_REG32(0x414)
+#define DISPC_IRQSTATUS                DISP_REG32(0x418)
+#define DISPC_IRQENABLE                DISP_REG32(0x41C)
+#define DISPC_CONFIG           DISP_REG32(0x444)
+#define DISPC_DEFAULT_COLOR0   DISP_REG32(0x44C)
+#define DISPC_DEFAULT_COLOR1   DISP_REG32(0x450)
+#define DISPC_TRANS_COLOR0     DISP_REG32(0x454)
+#define DISPC_TRANS_COLOR1     DISP_REG32(0x458)
+#define DISPC_LINE_NUMBER      DISP_REG32(0x460)
+#define DISPC_TIMING_H         DISP_REG32(0x464)
+#define DISPC_TIMING_V         DISP_REG32(0x468)
+#define DISPC_POL_FREQ         DISP_REG32(0x46C)
+#define DISPC_DIVISOR          DISP_REG32(0x470)
+#define DISPC_SIZE_DIG         DISP_REG32(0x478)
+#define DISPC_SIZE_LCD         DISP_REG32(0x47C)
+#define DISPC_GFX_BA0          DISP_REG32(0x480)
+#define DISPC_GFX_BA1          DISP_REG32(0x484)
+#define DISPC_GFX_POSITION     DISP_REG32(0x488)
+#define DISPC_GFX_SIZE         DISP_REG32(0x48C)
+#define DISPC_GFX_ATTRIBUTES   DISP_REG32(0x4A0)
+#define DISPC_GFX_FIFO_THRESHOLD       DISP_REG32(0x4A4)
+#define DISPC_GFX_ROW_INC      DISP_REG32(0x4AC)
+#define DISPC_GFX_PIXEL_INC    DISP_REG32(0x4B0)
+#define DISPC_GFX_WINDOW_SKIP  DISP_REG32(0x4B4)
+#define DISPC_GFX_TABLE_BA     DISP_REG32(0x4B8)
+#define DISPC_DATA_CYCLE1      DISP_REG32(0x5D4)
+#define DISPC_DATA_CYCLE2      DISP_REG32(0x5D8)
+#define DISPC_DATA_CYCLE3      DISP_REG32(0x5DC)
+
+/* Wake up define for board */
+#define GPIO97                 (1 << 1)
+#define GPIO88                 (1 << 24)
+
+#endif /* __ASSEMBLER__ */
+
+#endif
+
+
+
+
+
diff --git a/include/asm-arm/arch-omap/sram.h b/include/asm-arm/arch-omap/sram.h
new file mode 100644 (file)
index 0000000..e72ccbf
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm-arm/arch-omap/sram.h
+ *
+ * Interface for functions that need to be run in internal SRAM
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_OMAP_SRAM_H
+#define __ARCH_ARM_OMAP_SRAM_H
+
+extern void * omap_sram_push(void * start, unsigned long size);
+extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
+
+extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+                               u32 base_cs, u32 force_unlock);
+extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
+                                     u32 mem_type);
+extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
+
+
+/* Do not use these */
+extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
+extern unsigned long sram_reprogram_clock_sz;
+
+extern void sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+                         u32 base_cs, u32 force_unlock);
+extern unsigned long sram_ddr_init_sz;
+
+extern u32 sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
+extern unsigned long sram_set_prcm_sz;
+
+extern void sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type);
+extern unsigned long sram_reprogram_sdrc_sz;
+
+#endif
index ff37bc27e6034281e7686007210554c54377d420..90c2a059d9956766c439255c55febb69d909fbd1 100644 (file)
@@ -6,18 +6,21 @@
 #define __ASM_ARCH_SYSTEM_H
 #include <linux/config.h>
 #include <asm/mach-types.h>
+#include <asm/hardware/clock.h>
 #include <asm/arch/hardware.h>
-#include <asm/mach-types.h>
+#include <asm/arch/prcm.h>
+
+#ifndef CONFIG_MACH_VOICEBLUE
+#define voiceblue_reset()              do {} while (0)
+#endif
 
 static inline void arch_idle(void)
 {
        cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void omap1_arch_reset(char mode)
 {
-
-#ifdef CONFIG_ARCH_OMAP16XX
        /*
         * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
         * "Global Software Reset Affects Traffic Controller Frequency".
@@ -27,13 +30,31 @@ static inline void arch_reset(char mode)
                                 DPLL_CTL);
                omap_writew(0x8, ARM_RSTCT1);
        }
-#endif
-#ifdef CONFIG_MACH_VOICEBLUE
+
        if (machine_is_voiceblue())
                voiceblue_reset();
        else
-#endif
                omap_writew(1, ARM_RSTCT1);
 }
 
+static inline void omap2_arch_reset(char mode)
+{
+       u32 rate;
+       struct clk *vclk, *sclk;
+
+       vclk = clk_get(NULL, "virt_prcm_set");
+       sclk = clk_get(NULL, "sys_ck");
+       rate = clk_get_rate(sclk);
+       clk_set_rate(vclk, rate);       /* go to bypass for OMAP limitation */
+       RM_RSTCTRL_WKUP |= 2;
+}
+
+static inline void arch_reset(char mode)
+{
+       if (!cpu_is_omap24xx())
+               omap1_arch_reset(mode);
+       else
+               omap2_arch_reset(mode);                 
+}
+
 #endif
index b61ddb491e8318b3f48d5389063585b31f343f1e..21f2e367185a74bb4d3663f5c7c190bf8d705557 100644 (file)
 #if !defined(__ASM_ARCH_OMAP_TIMEX_H)
 #define __ASM_ARCH_OMAP_TIMEX_H
 
+/*
+ * OMAP 32KHz timer updates time one jiffie at a time from a secondary timer,
+ * and that's why the CLOCK_TICK_RATE is not 32768.
+ */
+#ifdef CONFIG_OMAP_32K_TIMER
+#define CLOCK_TICK_RATE                (CONFIG_OMAP_32K_TIMER_HZ)
+#else
 #define CLOCK_TICK_RATE                (HZ * 100000UL)
+#endif
 
 #endif /* __ASM_ARCH_OMAP_TIMEX_H */
index 3545c86859cc9a9700b02760a35fb1ba9a811ba8..9ea5144f1e29205120f75a665a676d2b32f28dcb 100644 (file)
@@ -35,11 +35,15 @@ putstr(const char *s)
 {
        volatile u8 * uart = 0;
        int shift = 2;
+       
+#ifdef CONFIG_MACH_OMAP_PALMTE
+       return;
+#endif
 
 #ifdef CONFIG_ARCH_OMAP
 #ifdef CONFIG_OMAP_LL_DEBUG_UART3
        uart = (volatile u8 *)(OMAP_UART3_BASE);
-#elif  CONFIG_OMAP_LL_DEBUG_UART2
+#elif defined(CONFIG_OMAP_LL_DEBUG_UART2)
        uart = (volatile u8 *)(OMAP_UART2_BASE);
 #else
        uart = (volatile u8 *)(OMAP_UART1_BASE);
index e3e8541ee63b07f57d915e5409e279d0f09ce2c6..18ca0c5dd8a0cac4b2fbbd22711a0b2c080e694e 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/config.h>
 #include <linux/mm.h> /* need struct page */
+#include <linux/device.h>
 
 #include <asm/scatterlist.h>
 
index 19da861e523d8dbbfe327e4b07d166c61544a623..609af9f8e6c59cfc42e8cd3b80176e47b81bf93f 100644 (file)
@@ -66,6 +66,12 @@ int clk_use(struct clk *clk);
  */
 void clk_unuse(struct clk *clk);
 
+/**
+ * clk_get_usecount - get the use count
+ * @clk: clock source
+ */
+int clk_get_usecount(struct clk *clk);
+
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *               This is only valid once the clock source has been enabled.
diff --git a/include/asm-arm/hardware/tsc2101.h b/include/asm-arm/hardware/tsc2101.h
new file mode 100644 (file)
index 0000000..4490458
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ *
+ * TI TSC2101 Audio CODEC and TS control registers definition 
+ *          
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *        source@mvista.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.
+ */
+
+#ifndef __ASM_HARDWARE_TSC2101_H
+#define __ASM_HARDWARE_TSC2101_H
+
+/* Page 0 Touch Screen Data Registers */
+#define TSC2101_TS_X                  (0x00)
+#define TSC2101_TS_Y                  (0x01)
+#define TSC2101_TS_Z1                 (0x02)
+#define TSC2101_TS_Z2                 (0x03)
+#define TSC2101_TS_BAT                (0x05)
+#define TSC2101_TS_AUX1               (0x07)
+#define TSC2101_TS_AUX2               (0x08)
+#define TSC2101_TS_TEMP1              (0x09)
+#define TSC2101_TS_TEMP2              (0x0A)
+
+/* Page 1 Touch Screen Control registers */
+#define TSC2101_TS_ADC_CTRL           (0x00)
+#define TSC2101_TS_STATUS             (0x01)
+#define TSC2101_TS_BUFFER_CTRL        (0x02)
+#define TSC2101_TS_REF_CTRL           (0x03)
+#define TSC2101_TS_RESET_CTRL         (0x04)
+#define TSC2101_TS_CONFIG_CTRL        (0x05)
+#define TSC2101_TS_TEMP_MAX_THRESHOLD (0x06)
+#define TSC2101_TS_TEMP_MIN_THRESHOLD (0x07)
+#define TSC2101_TS_AUX1_MAX_THRESHOLD (0x08)
+#define TSC2101_TS_AUX1_MIN_THRESHOLD (0x09)
+#define TSC2101_TS_AUX2_MAX_THRESHOLD (0x0A)
+#define TSC2101_TS_AUX2_MIN_THRESHOLD (0x0B)
+#define TSC2101_TS_MEASURE_CONFIG     (0x0C)
+#define TSC2101_TS_PROG_DELAY         (0x0D)
+
+/* Page 2 Audio codec Control registers */
+#define TSC2101_AUDIO_CTRL_1          (0x00)
+#define TSC2101_HEADSET_GAIN_CTRL     (0x01)
+#define TSC2101_DAC_GAIN_CTRL         (0x02)
+#define TSC2101_MIXER_PGA_CTRL        (0x03)
+#define TSC2101_AUDIO_CTRL_2          (0x04)
+#define TSC2101_CODEC_POWER_CTRL      (0x05)
+#define TSC2101_AUDIO_CTRL_3          (0x06)
+#define TSC2101_LCH_BASS_BOOST_N0     (0x07)
+#define TSC2101_LCH_BASS_BOOST_N1     (0x08)
+#define TSC2101_LCH_BASS_BOOST_N2     (0x09)
+#define TSC2101_LCH_BASS_BOOST_N3     (0x0A)
+#define TSC2101_LCH_BASS_BOOST_N4     (0x0B)
+#define TSC2101_LCH_BASS_BOOST_N5     (0x0C)
+#define TSC2101_LCH_BASS_BOOST_D1     (0x0D)
+#define TSC2101_LCH_BASS_BOOST_D2     (0x0E)
+#define TSC2101_LCH_BASS_BOOST_D4     (0x0F)
+#define TSC2101_LCH_BASS_BOOST_D5     (0x10)
+#define TSC2101_RCH_BASS_BOOST_N0     (0x11)
+#define TSC2101_RCH_BASS_BOOST_N1     (0x12)
+#define TSC2101_RCH_BASS_BOOST_N2     (0x13)
+#define TSC2101_RCH_BASS_BOOST_N3     (0x14)
+#define TSC2101_RCH_BASS_BOOST_N4     (0x15)
+#define TSC2101_RCH_BASS_BOOST_N5     (0x16)
+#define TSC2101_RCH_BASS_BOOST_D1     (0x17)
+#define TSC2101_RCH_BASS_BOOST_D2     (0x18)
+#define TSC2101_RCH_BASS_BOOST_D4     (0x19)
+#define TSC2101_RCH_BASS_BOOST_D5     (0x1A)
+#define TSC2101_PLL_PROG_1            (0x1B)
+#define TSC2101_PLL_PROG_2            (0x1C)
+#define TSC2101_AUDIO_CTRL_4          (0x1D)
+#define TSC2101_HANDSET_GAIN_CTRL     (0x1E)
+#define TSC2101_BUZZER_GAIN_CTRL      (0x1F)
+#define TSC2101_AUDIO_CTRL_5          (0x20)
+#define TSC2101_AUDIO_CTRL_6          (0x21)
+#define TSC2101_AUDIO_CTRL_7          (0x22)
+#define TSC2101_GPIO_CTRL             (0x23)
+#define TSC2101_AGC_CTRL              (0x24)
+#define TSC2101_POWERDOWN_STS         (0x25)
+#define TSC2101_MIC_AGC_CONTROL       (0x26)
+#define TSC2101_CELL_AGC_CONTROL      (0x27)
+
+/* Bit field definitions for TS Control */
+#define TSC2101_DATA_AVAILABLE         0x4000
+#define TSC2101_BUFFERMODE_DISABLE     0x0
+#define TSC2101_REF_POWERUP            0x16
+#define TSC2101_ENABLE_TOUCHDETECT     0x08
+#define TSC2101_PRG_DELAY              0x0900
+#define TSC2101_ADC_CONTROL            0x8874
+#define TSC2101_ADC_POWERDOWN          0x4000
+
+/* Bit position */
+#define TSC2101_BIT(ARG)    ((0x01)<<(ARG))
+
+/* Field masks for Audio Control 1 */
+#define AC1_ADCHPF(ARG)     (((ARG) & 0x03) << 14)
+#define AC1_WLEN(ARG)       (((ARG) & 0x03) << 10)
+#define AC1_DATFM(ARG)      (((ARG) & 0x03) << 8)
+#define AC1_DACFS(ARG)      (((ARG) & 0x07) << 3)
+#define AC1_ADCFS(ARG)      (((ARG) & 0x07))
+
+/* Field masks for TSC2101_HEADSET_GAIN_CTRL */
+#define HGC_ADMUT_HED       TSC2101_BIT(15)
+#define HGC_ADPGA_HED(ARG)  (((ARG) & 0x7F) << 8)
+#define HGC_AGCTG_HED(ARG)  (((ARG) & 0x07) << 5)
+#define HGC_AGCTC_HED(ARG)  (((ARG) & 0x0F) << 1)
+#define HGC_AGCEN_HED       (0x01)
+
+/* Field masks for TSC2101_DAC_GAIN_CTRL */
+#define DGC_DALMU           TSC2101_BIT(15)
+#define DGC_DALVL(ARG)      (((ARG) & 0x7F) << 8)
+#define DGC_DARMU           TSC2101_BIT(7)
+#define DGC_DARVL(ARG)      (((ARG) & 0x7F))
+
+/* Field masks for TSC2101_MIXER_PGA_CTRL */
+#define MPC_ASTMU           TSC2101_BIT(15)
+#define MPC_ASTG(ARG)       (((ARG) & 0x7F) << 8)
+#define MPC_MICSEL(ARG)     (((ARG) & 0x07) << 5)
+#define MPC_MICADC          TSC2101_BIT(4)
+#define MPC_CPADC           TSC2101_BIT(3)
+#define MPC_ASTGF           (0x01)
+
+/* Field formats for TSC2101_AUDIO_CTRL_2 */
+#define AC2_KCLEN           TSC2101_BIT(15)
+#define AC2_KCLAC(ARG)      (((ARG) & 0x07) << 12)
+#define AC2_APGASS          TSC2101_BIT(11)
+#define AC2_KCLFRQ(ARG)     (((ARG) & 0x07) << 8)
+#define AC2_KCLLN(ARG)      (((ARG) & 0x0F) << 4)
+#define AC2_DLGAF           TSC2101_BIT(3)
+#define AC2_DRGAF           TSC2101_BIT(2)
+#define AC2_DASTC           TSC2101_BIT(1)
+#define AC2_ADGAF           (0x01)
+
+/* Field masks for TSC2101_CODEC_POWER_CTRL */
+#define CPC_MBIAS_HND       TSC2101_BIT(15)
+#define CPC_MBIAS_HED       TSC2101_BIT(14)
+#define CPC_ASTPWD          TSC2101_BIT(13)
+#define CPC_SP1PWDN         TSC2101_BIT(12)
+#define CPC_SP2PWDN         TSC2101_BIT(11)
+#define CPC_DAPWDN          TSC2101_BIT(10)
+#define CPC_ADPWDN          TSC2101_BIT(9)
+#define CPC_VGPWDN          TSC2101_BIT(8)
+#define CPC_COPWDN          TSC2101_BIT(7)
+#define CPC_LSPWDN          TSC2101_BIT(6)
+#define CPC_ADPWDF          TSC2101_BIT(5)
+#define CPC_LDAPWDF         TSC2101_BIT(4)
+#define CPC_RDAPWDF         TSC2101_BIT(3)
+#define CPC_ASTPWF          TSC2101_BIT(2)
+#define CPC_BASSBC          TSC2101_BIT(1)
+#define CPC_DEEMPF          (0x01)
+
+/* Field masks for TSC2101_AUDIO_CTRL_3 */
+#define AC3_DMSVOL(ARG)     (((ARG) & 0x03) << 14)
+#define AC3_REFFS           TSC2101_BIT(13)
+#define AC3_DAXFM           TSC2101_BIT(12)
+#define AC3_SLVMS           TSC2101_BIT(11)
+#define AC3_ADCOVF          TSC2101_BIT(8)
+#define AC3_DALOVF          TSC2101_BIT(7)
+#define AC3_DAROVF          TSC2101_BIT(6)
+#define AC3_CLPST           TSC2101_BIT(3)
+#define AC3_REVID(ARG)      (((ARG) & 0x07))
+
+/* Field masks for TSC2101_PLL_PROG_1 */
+#define PLL1_PLLSEL         TSC2101_BIT(15)
+#define PLL1_QVAL(ARG)      (((ARG) & 0x0F) << 11)
+#define PLL1_PVAL(ARG)      (((ARG) & 0x07) << 8)
+#define PLL1_I_VAL(ARG)     (((ARG) & 0x3F) << 2)
+
+/* Field masks of TSC2101_PLL_PROG_2 */
+#define PLL2_D_VAL(ARG)     (((ARG) & 0x3FFF) << 2)
+
+/* Field masks for TSC2101_AUDIO_CTRL_4 */
+#define AC4_ADSTPD          TSC2101_BIT(15)
+#define AC4_DASTPD          TSC2101_BIT(14)
+#define AC4_ASSTPD          TSC2101_BIT(13)
+#define AC4_CISTPD          TSC2101_BIT(12)
+#define AC4_BISTPD          TSC2101_BIT(11)
+#define AC4_AGCHYS(ARG)     (((ARG) & 0x03) << 9)
+#define AC4_MB_HED(ARG)     (((ARG) & 0x03) << 7)
+#define AC4_MB_HND          TSC2101_BIT(6)
+#define AC4_SCPFL           TSC2101_BIT(1)
+
+/* Field masks settings for TSC2101_HANDSET_GAIN_CTRL */
+#define HNGC_ADMUT_HND      TSC2101_BIT(15)
+#define HNGC_ADPGA_HND(ARG) (((ARG) & 0x7F) << 8)
+#define HNGC_AGCTG_HND(ARG) (((ARG) & 0x07) << 5)
+#define HNGC_AGCTC_HND(ARG) (((ARG) & 0x0F) << 1)
+#define HNGC_AGCEN_HND      (0x01)
+
+/* Field masks settings for TSC2101_BUZZER_GAIN_CTRL */
+#define BGC_MUT_CP          TSC2101_BIT(15)
+#define BGC_CPGA(ARG)       (((ARG) & 0x7F) << 8)
+#define BGC_CPGF            TSC2101_BIT(7)
+#define BGC_MUT_BU          TSC2101_BIT(6)
+#define BGC_BPGA(ARG)       (((ARG) & 0x0F) << 2)
+#define BGC_BUGF            TSC2101_BIT(1)
+
+/* Field masks settings for TSC2101_AUDIO_CTRL_5 */
+#define AC5_DIFFIN          TSC2101_BIT(15)
+#define AC5_DAC2SPK1(ARG)   (((ARG) & 0x03) << 13)
+#define AC5_AST2SPK1        TSC2101_BIT(12)
+#define AC5_BUZ2SPK1        TSC2101_BIT(11)
+#define AC5_KCL2SPK1        TSC2101_BIT(10)
+#define AC5_CPI2SPK1        TSC2101_BIT(9)
+#define AC5_DAC2SPK2(ARG)   (((ARG) & 0x03) << 7)
+#define AC5_AST2SPK2        TSC2101_BIT(6)
+#define AC5_BUZ2SPK2        TSC2101_BIT(5)
+#define AC5_KCL2SPK2        TSC2101_BIT(4)
+#define AC5_CPI2SPK2        TSC2101_BIT(3)
+#define AC5_MUTSPK1         TSC2101_BIT(2)
+#define AC5_MUTSPK2         TSC2101_BIT(1)
+#define AC5_HDSCPTC         (0x01)
+
+/* Field masks settings for TSC2101_AUDIO_CTRL_6 */
+#define AC6_SPL2LSK         TSC2101_BIT(15)
+#define AC6_AST2LSK         TSC2101_BIT(14)
+#define AC6_BUZ2LSK         TSC2101_BIT(13)
+#define AC6_KCL2LSK         TSC2101_BIT(12)
+#define AC6_CPI2LSK         TSC2101_BIT(11)
+#define AC6_MIC2CPO         TSC2101_BIT(10)
+#define AC6_SPL2CPO         TSC2101_BIT(9)
+#define AC6_SPR2CPO         TSC2101_BIT(8)
+#define AC6_MUTLSPK         TSC2101_BIT(7)
+#define AC6_MUTSPK2         TSC2101_BIT(6)
+#define AC6_LDSCPTC         TSC2101_BIT(5)
+#define AC6_VGNDSCPTC       TSC2101_BIT(4)
+#define AC6_CAPINTF         TSC2101_BIT(3)
+
+/* Field masks settings for TSC2101_AUDIO_CTRL_7 */
+#define AC7_DETECT          TSC2101_BIT(15)
+#define AC7_HESTYPE(ARG)    (((ARG) & 0x03) << 13)
+#define AC7_HDDETFL         TSC2101_BIT(12)
+#define AC7_BDETFL          TSC2101_BIT(11)
+#define AC7_HDDEBNPG(ARG)   (((ARG) & 0x03) << 9)
+#define AC7_BDEBNPG(ARG)    (((ARG) & 0x03) << 6)
+#define AC7_DGPIO2          TSC2101_BIT(4)
+#define AC7_DGPIO1          TSC2101_BIT(3)
+#define AC7_CLKGPIO2        TSC2101_BIT(2)
+#define AC7_ADWSF(ARG)      (((ARG) & 0x03))
+
+/* Field masks settings for TSC2101_GPIO_CTRL */
+#define GC_GPO2EN           TSC2101_BIT(15)
+#define GC_GPO2SG           TSC2101_BIT(14)
+#define GC_GPI2EN           TSC2101_BIT(13)
+#define GC_GPI2SGF          TSC2101_BIT(12)
+#define GC_GPO1EN           TSC2101_BIT(11)
+#define GC_GPO1SG           TSC2101_BIT(10)
+#define GC_GPI1EN           TSC2101_BIT(9)
+#define GC_GPI1SGF          TSC2101_BIT(8)
+
+/* Field masks for TSC2101_AGC_CTRL */
+#define AC_AGCNF_CELL       TSC2101_BIT(14)
+#define AC_AGCNL(ARG)       (((ARG) & 0x07) << 11)
+#define AC_AGCHYS_CELL(ARG) (((ARG) & 0x03) << 9)
+#define AC_CLPST_CELL       TSC2101_BIT(8)
+#define AC_AGCTG_CELL(ARG)  (((ARG) & 0x07) << 5)
+#define AC_AGCTC_CELL(ARG)  (((ARG) & 0x0F) << 1)
+#define AC_AGCEN_CELL       (0x01)
+
+/* Field masks for TSC2101_POWERDOWN_STS */
+#define PS_SPK1FL            TSC2101_BIT(15)
+#define PS_SPK2FL            TSC2101_BIT(14)
+#define PS_HNDFL             TSC2101_BIT(13)
+#define PS_VGNDFL            TSC2101_BIT(12)
+#define PS_LSPKFL            TSC2101_BIT(11)
+#define PS_CELLFL            TSC2101_BIT(10)
+#define PS_PSEQ              TSC2101_BIT(5)
+#define PS_PSTIME            TSC2101_BIT(4)
+
+/* Field masks for Register Mic AGC Control */
+#define MAC_MMPGA(ARG)       (((ARG) & 0x7F) << 9)
+#define MAC_MDEBNS(ARG)      (((ARG) & 0x07) << 6)
+#define MAC_MDEBSN(ARG)      (((ARG) & 0x07) << 3)
+
+/* Field masks for Register Cellphone AGC Control */
+#define CAC_CMPGA(ARG)       (((ARG) & 0x7F) << 9)
+#define CAC_CDEBNS(ARG)      (((ARG) & 0x07) << 6)
+#define CAC_CDEBSN(ARG)      (((ARG) & 0x07) << 3)
+
+#endif                         /* __ASM_HARDWARE_TSC2101_H */
index ea3ed24652333e8dbcc3020074a626050895ed84..b0d181e7c0f70a872e6d7db86a27f0e3fddf9671 100644 (file)
@@ -134,6 +134,13 @@ struct tag_acorn {
        u8 adfsdrives;
 };
 
+/* TI OMAP specific information */
+#define ATAG_BOARD       0x414f4d50
+
+struct tag_omap {
+       u8 data[0];
+};
+
 /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
 #define ATAG_MEMCLK    0x41000402
 
@@ -159,6 +166,11 @@ struct tag {
                 */
                struct tag_acorn        acorn;
 
+               /*
+                * OMAP specific
+                 */
+                struct tag_omap         omap;
+
                /*
                 * DC21285 specific
                 */
index 04a58f33ec53b5e33d98d046049b3b7d4fe512b3..16ace117cb14cd308f36fbaba1640d95da1941ea 100644 (file)
 #define FB_ACCEL_NV_40          46      /* nVidia Arch 40               */
 #define FB_ACCEL_XGI_VOLARI_V  47      /* XGI Volari V3XT, V5, V8      */
 #define FB_ACCEL_XGI_VOLARI_Z  48      /* XGI Volari Z7                */
+#define FB_ACCEL_OMAP1610       49     /* TI OMAP16xx                  */
 #define FB_ACCEL_NEOMAGIC_NM2070 90    /* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91    /* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92    /* NeoMagic NM2093              */
index 3c5823368ddb4e680f0bf702e75efd4eed4e8d97..44ef1f89ba26ac8c02c57de6e58934b9f4639d1c 100644 (file)
@@ -333,10 +333,22 @@ struct input_absinfo {
 #define KEY_BRIGHTNESSUP       225
 #define KEY_MEDIA              226
 
-#define KEY_SWITCHVIDEOMODE    227
-#define KEY_KBDILLUMTOGGLE     228
-#define KEY_KBDILLUMDOWN       229
-#define KEY_KBDILLUMUP         230
+
+/*Zeus: these keys are defined for OMAP730 Perseus2*/
+#define KEY_STAR               227
+#define KEY_SHARP              228
+#define KEY_SOFT1              229
+#define KEY_SOFT2              230
+#define KEY_SEND               231
+#define KEY_CENTER             232
+#define KEY_HEADSETHOOK                233
+#define KEY_0_5                        234
+#define KEY_2_5                        235
+
+#define KEY_SWITCHVIDEOMODE    236
+#define KEY_KBDILLUMTOGGLE     237
+#define KEY_KBDILLUMDOWN       238
+#define KEY_KBDILLUMUP         239
 
 #define KEY_SEND               231
 #define KEY_REPLY              232
index b27c11064409a35812d9d35ba359e06f6d8c0ffb..d63da86037b76865094b2ac5d05a867ea26d5921 100644 (file)
@@ -286,6 +286,7 @@ void __init mount_block_root(char *name, int flags)
        char *fs_names = __getname();
        char *p;
        char b[BDEVNAME_SIZE];
+       int i = 0;
 
        get_fs_names(fs_names);
 retry:
@@ -300,6 +301,14 @@ retry:
                        case -EINVAL:
                                continue;
                }
+
+               printk("VFS: No root yet, retrying to mount root on %s (%s)\n",
+                      root_device_name, __bdevname(ROOT_DEV, b));
+               current->state = TASK_INTERRUPTIBLE;
+               schedule_timeout(10 * HZ);
+               if (i++ < 5)
+                       goto retry;
+
                /*
                 * Allow the user to distinguish between failed sys_open
                 * and bad superblock on root device.
index e9be027bc9300d03322a7ecf5681bdb2dec69f4b..d26e669c23daa3d568dd38ebff9d22e17febe9d1 100644 (file)
 
 #define __LOG_BUF_LEN  (1 << CONFIG_LOG_BUF_SHIFT)
 
+#ifdef        CONFIG_DEBUG_LL
+extern void printascii(char *);
+#endif
+
 /* printk's without a loglevel use this.. */
 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
 
@@ -541,6 +545,10 @@ asmlinkage int vprintk(const char *fmt, va_list args)
        /* Emit the output into the temporary buffer */
        printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
 
+#ifdef CONFIG_DEBUG_LL
+       printascii(printk_buf);
+#endif
+
        /*
         * Copy the output into log_buf.  If the caller didn't provide
         * appropriate log level tags, we insert them here
index 0864a7ce414d7bddb48a7497314e90a5d956d159..48d94d4c38980ef9f1d60d03f8cb1066382a21c9 100644 (file)
@@ -34,4 +34,16 @@ config SND_PXA2XX_AC97
          Say Y or M if you want to support any AC97 codec attached to
          the PXA2xx AC97 interface.
 
+config SND_OMAP_AIC23
+       tristate "OMAP AIC23 alsa driver (osk5912)"
+       depends on ARCH_OMAP && SND
+       select SND_PCM
+       select SENSORS_TLV320AIC23
+       help
+         Say Y here if you have a OSK platform board
+         and want to use its AIC23 audio chip.
+
+         To compile this driver as a module, choose M here: the module
+         will be called snd-omap-aic23.
+
 endmenu
index 4ef6dd00c6eeafb9916378ad7098b642a309a0cc..019a9f03c2c02c13a8b51af2efc756f06d0bf329 100644 (file)
@@ -13,3 +13,6 @@ snd-pxa2xx-pcm-objs           := pxa2xx-pcm.o
 
 obj-$(CONFIG_SND_PXA2XX_AC97)  += snd-pxa2xx-ac97.o
 snd-pxa2xx-ac97-objs           := pxa2xx-ac97.o
+
+obj-$(CONFIG_SND_OMAP_AIC23) += snd-omap-aic23.o
+snd-omap-aic23-objs := omap-aic23.o omap-alsa-dma.o omap-alsa-mixer.o
diff --git a/sound/arm/omap-aic23.c b/sound/arm/omap-aic23.c
new file mode 100644 (file)
index 0000000..9c651cf
--- /dev/null
@@ -0,0 +1,904 @@
+/*
+ * sound/arm/omap-aic23.c
+ * 
+ * Alsa Driver for AIC23 codec on OSK5912 platform board
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by Daniel Petrini, David Cohen, Anderson Briglia
+ *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
+ *
+ * Based on sa11xx-uda1341.c, 
+ * Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
+ *
+ * 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.
+ *
+ * History:
+ *
+ * 2005-07-29   INdT Kernel Team - Alsa driver for omap osk. Creation of new 
+ *                                 file omap-aic23.c
+ */
+
+#include <linux/config.h>
+#include <sound/driver.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/aic23.h>
+#include <asm/hardware/clock.h>
+#include <asm/arch/mcbsp.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/memalloc.h>
+
+#include "omap-alsa-dma.h"
+#include "omap-aic23.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define ADEBUG() printk("XXX Alsa debug f:%s, l:%d\n", __FUNCTION__, __LINE__)
+#else
+#define ADEBUG()               /* nop */
+#endif
+
+/* Define to set the AIC23 as the master w.r.t McBSP */
+#define AIC23_MASTER
+
+/*
+ * AUDIO related MACROS
+ */
+#define DEFAULT_BITPERSAMPLE          16
+#define AUDIO_RATE_DEFAULT           44100
+#define AUDIO_MCBSP                   OMAP_MCBSP1
+#define NUMBER_SAMPLE_RATES_SUPPORTED 10
+
+
+MODULE_AUTHOR("Daniel Petrini, David Cohen, Anderson Briglia - INdT");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("OMAP AIC23 driver for ALSA");
+MODULE_SUPPORTED_DEVICE("{{AIC23,OMAP AIC23}}");
+MODULE_ALIAS("omap_mcbsp.1");
+
+static char *id = NULL;        
+MODULE_PARM_DESC(id, "OMAP OSK ALSA Driver for AIC23 chip.");
+
+static struct snd_card_omap_aic23 *omap_aic23 = NULL;
+
+static struct clk *aic23_mclk = 0;
+
+struct sample_rate_rate_reg_info {
+       u8 control;             /* SR3, SR2, SR1, SR0 and BOSR */
+       u8 divider;             /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
+};
+
+/*
+ * DAC USB-mode sampling rates (MCLK = 12 MHz)
+ * The rates and rate_reg_into MUST be in the same order
+ */
+static unsigned int rates[] = {
+       4000, 8000, 16000, 22050,
+       24000, 32000, 44100,
+       48000, 88200, 96000,
+};
+static const struct sample_rate_rate_reg_info
+ rate_reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
+       {0x06, 1},              /*  4000 */
+       {0x06, 0},              /*  8000 */
+       {0x0C, 1},              /* 16000 */
+       {0x11, 1},              /* 22050 */
+       {0x00, 1},              /* 24000 */
+       {0x0C, 0},              /* 32000 */
+       {0x11, 0},              /* 44100 */
+       {0x00, 0},              /* 48000 */
+       {0x1F, 0},              /* 88200 */
+       {0x0E, 0},              /* 96000 */
+};
+
+/*
+ *  mcbsp configuration structure
+ */
+static struct omap_mcbsp_reg_cfg initial_config_mcbsp = {
+       .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+       .spcr1 = RINTM(3) | RRST,
+       .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+           RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+       .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+       .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+           XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+       .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+       .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+       .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+#ifndef AIC23_MASTER
+       /* configure McBSP to be the I2S master */
+       .pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
+#else
+       /* configure McBSP to be the I2S slave */
+       .pcr0 = CLKXP | CLKRP,
+#endif                         /* AIC23_MASTER */
+};
+
+static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+       .count = ARRAY_SIZE(rates),
+       .list = rates,
+       .mask = 0,
+};
+
+
+/*
+ * Codec/mcbsp init and configuration section
+ * codec dependent code.
+ */
+
+/*
+ * Sample rate changing
+ */
+static void omap_aic23_set_samplerate(struct snd_card_omap_aic23
+                                     *omap_aic23, long rate)
+{
+       u8 count = 0;
+       u16 data = 0;
+
+       /* Fix the rate if it has a wrong value */
+       if (rate >= 96000)
+               rate = 96000;
+       else if (rate >= 88200)
+               rate = 88200;
+       else if (rate >= 48000)
+               rate = 48000;
+       else if (rate >= 44100)
+               rate = 44100;
+       else if (rate >= 32000)
+               rate = 32000;
+       else if (rate >= 24000)
+               rate = 24000;
+       else if (rate >= 22050)
+               rate = 22050;
+       else if (rate >= 16000)
+               rate = 16000;
+       else if (rate >= 8000)
+               rate = 8000;
+       else
+               rate = 4000;
+
+       /* Search for the right sample rate */
+       /* Verify what happens if the rate is not supported
+        * now it goes to 96Khz */
+       while ((rates[count] != rate) &&
+              (count < (NUMBER_SAMPLE_RATES_SUPPORTED - 1))) {
+               count++;
+       }
+
+       data = (rate_reg_info[count].divider << CLKIN_SHIFT) |
+           (rate_reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
+
+       audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
+
+       omap_aic23->samplerate = rate;
+}
+
+static inline void aic23_configure(void)
+{
+       /* Reset codec */
+       audio_aic23_write(RESET_CONTROL_ADDR, 0);
+
+       /* Initialize the AIC23 internal state */
+
+       /* Analog audio path control, DAC selected, delete INSEL_MIC for line in */
+       audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR, DEFAULT_ANALOG_AUDIO_CONTROL);
+
+       /* Digital audio path control, de-emphasis control 44.1kHz */
+       audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
+
+       /* Digital audio interface, master/slave mode, I2S, 16 bit */
+#ifdef AIC23_MASTER
+       audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR,
+                         MS_MASTER | IWL_16 | FOR_DSP);
+#else
+       audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
+#endif
+
+       /* Enable digital interface */
+       audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
+
+}
+
+static void omap_aic23_audio_init(struct snd_card_omap_aic23 *omap_aic23)
+{
+       /* Setup DMA stuff */
+       omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].id = "Alsa AIC23 out";
+       omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id =
+           SNDRV_PCM_STREAM_PLAYBACK;
+       omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev =
+           OMAP_DMA_MCBSP1_TX;
+
+       omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].id = "Alsa AIC23 in";
+       omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].stream_id =
+           SNDRV_PCM_STREAM_CAPTURE;
+       omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev =
+           OMAP_DMA_MCBSP1_RX;
+
+       /* configuring the McBSP */
+       omap_mcbsp_request(AUDIO_MCBSP);
+
+       /* if configured, then stop mcbsp */
+       omap_mcbsp_stop(AUDIO_MCBSP);
+
+       omap_mcbsp_config(AUDIO_MCBSP, &initial_config_mcbsp);
+       omap_mcbsp_start(AUDIO_MCBSP);
+       aic23_configure();
+}
+
+/* 
+ * DMA functions 
+ * Depends on omap-aic23-dma.c functions and (omap) dma.c
+ * 
+ */
+#define DMA_BUF_SIZE   1024 * 8
+
+static int audio_dma_request(struct audio_stream *s,
+                            void (*callback) (void *))
+{
+       int err;
+
+       err = omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);
+       if (err < 0)
+               printk(KERN_ERR "unable to grab audio dma 0x%x\n",
+                      s->dma_dev);
+       return err;
+}
+
+static int audio_dma_free(struct audio_stream *s)
+{
+       int err = 0;
+
+       err = omap_free_sound_dma(s, &s->lch);
+       if (err < 0)
+               printk(KERN_ERR "Unable to free audio dma channels!\n");
+       return err;
+}
+
+/*
+ *  This function should calculate the current position of the dma in the
+ *  buffer. It will help alsa middle layer to continue update the buffer.
+ *  Its correctness is crucial for good functioning.
+ */
+static u_int audio_get_dma_pos(struct audio_stream *s)
+{
+       snd_pcm_substream_t *substream = s->stream;
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       unsigned int offset;
+       unsigned long flags;
+       dma_addr_t count;
+       ADEBUG();
+
+       /* this must be called w/ interrupts locked as requested in dma.c */
+       spin_lock_irqsave(&s->dma_lock, flags);
+
+       /* For the current period let's see where we are */
+       count = omap_get_dma_src_addr_counter(s->lch[s->dma_q_head]);
+
+       spin_unlock_irqrestore(&s->dma_lock, flags);
+
+       /* Now, the position related to the end of that period */
+       offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, count);
+
+       if (offset >= runtime->buffer_size || offset < 0)
+               offset = 0;
+
+       return offset;
+}
+
+/*
+ * this stops the dma and clears the dma ptrs
+ */
+static void audio_stop_dma(struct audio_stream *s)
+{
+       unsigned long flags;
+       ADEBUG();
+
+       spin_lock_irqsave(&s->dma_lock, flags);
+       s->active = 0;
+       s->period = 0;
+       s->periods = 0;
+
+       /* this stops the dma channel and clears the buffer ptrs */
+       omap_audio_stop_dma(s);
+
+       omap_clear_sound_dma(s);
+
+       spin_unlock_irqrestore(&s->dma_lock, flags);
+}
+
+/*
+ *  Main dma routine, requests dma according where you are in main alsa buffer
+ */
+static void audio_process_dma(struct audio_stream *s)
+{
+       snd_pcm_substream_t *substream = s->stream;
+       snd_pcm_runtime_t *runtime;
+       unsigned int dma_size;
+       unsigned int offset;
+       int ret;
+
+       runtime = substream->runtime;
+       if (s->active) {
+               dma_size = frames_to_bytes(runtime, runtime->period_size);
+               offset = dma_size * s->period;
+               snd_assert(dma_size <= DMA_BUF_SIZE,);
+               ret =
+                   omap_start_sound_dma(s,
+                                        (dma_addr_t) runtime->dma_area +
+                                        offset, dma_size);
+               if (ret) {
+                       printk(KERN_ERR
+                              "audio_process_dma: cannot queue DMA buffer (%i)\n",
+                              ret);
+                       return;
+               }
+
+               s->period++;
+               s->period %= runtime->periods;
+               s->periods++;
+               s->offset = offset;
+       }
+}
+
+/* 
+ *  This is called when dma IRQ occurs at the end of each transmited block
+ */
+void audio_dma_callback(void *data)
+{
+       struct audio_stream *s = data;
+
+       /* 
+        * If we are getting a callback for an active stream then we inform
+        * the PCM middle layer we've finished a period
+        */
+       if (s->active)
+               snd_pcm_period_elapsed(s->stream);
+
+       spin_lock(&s->dma_lock);
+       if (s->periods > 0) {
+               s->periods--;
+       }
+       audio_process_dma(s);
+       spin_unlock(&s->dma_lock);
+}
+
+
+/* 
+ * Alsa section
+ * PCM settings and callbacks
+ */
+
+static int snd_omap_aic23_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+       struct snd_card_omap_aic23 *chip =
+           snd_pcm_substream_chip(substream);
+       int stream_id = substream->pstr->stream;
+       struct audio_stream *s = &chip->s[stream_id];
+       int err = 0;
+       ADEBUG();
+
+       /* note local interrupts are already disabled in the midlevel code */
+       spin_lock(&s->dma_lock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               /* requested stream startup */
+               s->active = 1;
+               audio_process_dma(s);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               /* requested stream shutdown */
+               audio_stop_dma(s);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       spin_unlock(&s->dma_lock);
+       
+       return err;
+}
+
+static int snd_omap_aic23_prepare(snd_pcm_substream_t * substream)
+{
+       struct snd_card_omap_aic23 *chip =
+           snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       struct audio_stream *s = &chip->s[substream->pstr->stream];
+
+       /* set requested samplerate */
+       omap_aic23_set_samplerate(chip, runtime->rate);
+
+       s->period = 0;
+       s->periods = 0;
+
+       return 0;
+}
+
+static snd_pcm_uframes_t snd_omap_aic23_pointer(snd_pcm_substream_t *
+                                               substream)
+{
+       struct snd_card_omap_aic23 *chip =
+           snd_pcm_substream_chip(substream);
+       
+       return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
+}
+
+/* Hardware capabilities */
+
+static snd_pcm_hardware_t snd_omap_aic23_capture = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
+       .formats = (SNDRV_PCM_FMTBIT_S16_LE),
+       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
+                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+                 SNDRV_PCM_RATE_KNOT),
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 128 * 1024,
+       .period_bytes_min = 32,
+       .period_bytes_max = 8 * 1024,
+       .periods_min = 16,
+       .periods_max = 255,
+       .fifo_size = 0,
+};
+
+static snd_pcm_hardware_t snd_omap_aic23_playback = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),      
+       .formats = (SNDRV_PCM_FMTBIT_S16_LE),
+       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
+                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+                 SNDRV_PCM_RATE_KNOT),
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 128 * 1024,
+       .period_bytes_min = 32,
+       .period_bytes_max = 8 * 1024,
+       .periods_min = 16,
+       .periods_max = 255,
+       .fifo_size = 0,
+};
+
+static int snd_card_omap_aic23_open(snd_pcm_substream_t * substream)
+{
+       struct snd_card_omap_aic23 *chip =
+           snd_pcm_substream_chip(substream);
+       snd_pcm_runtime_t *runtime = substream->runtime;
+       int stream_id = substream->pstr->stream;
+       int err;
+       ADEBUG();
+
+       chip->s[stream_id].stream = substream;
+       
+       omap_aic23_clock_on();
+       
+       if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
+               runtime->hw = snd_omap_aic23_playback;
+       else
+               runtime->hw = snd_omap_aic23_capture;
+       if ((err =
+            snd_pcm_hw_constraint_integer(runtime,
+                                          SNDRV_PCM_HW_PARAM_PERIODS)) <
+           0)
+               return err;
+       if ((err =
+            snd_pcm_hw_constraint_list(runtime, 0,
+                                       SNDRV_PCM_HW_PARAM_RATE,
+                                       &hw_constraints_rates)) < 0)
+               return err;
+
+       return 0;
+}
+
+static int snd_card_omap_aic23_close(snd_pcm_substream_t * substream)
+{
+       struct snd_card_omap_aic23 *chip =
+           snd_pcm_substream_chip(substream);
+       ADEBUG();
+       
+       omap_aic23_clock_off();
+       chip->s[substream->pstr->stream].stream = NULL;
+       
+       return 0;
+}
+
+/* HW params & free */
+
+static int snd_omap_aic23_hw_params(snd_pcm_substream_t * substream,
+                                   snd_pcm_hw_params_t * hw_params)
+{
+       return snd_pcm_lib_malloc_pages(substream,
+                                       params_buffer_bytes(hw_params));
+}
+
+static int snd_omap_aic23_hw_free(snd_pcm_substream_t * substream)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
+/* pcm operations */
+
+static snd_pcm_ops_t snd_card_omap_aic23_playback_ops = {
+       .open =         snd_card_omap_aic23_open,
+       .close =        snd_card_omap_aic23_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_omap_aic23_hw_params,
+       .hw_free =      snd_omap_aic23_hw_free,
+       .prepare =      snd_omap_aic23_prepare,
+       .trigger =      snd_omap_aic23_trigger,
+       .pointer =      snd_omap_aic23_pointer,
+};
+
+static snd_pcm_ops_t snd_card_omap_aic23_capture_ops = {
+       .open =         snd_card_omap_aic23_open,
+       .close =        snd_card_omap_aic23_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_omap_aic23_hw_params,
+       .hw_free =      snd_omap_aic23_hw_free,
+       .prepare =      snd_omap_aic23_prepare,
+       .trigger =      snd_omap_aic23_trigger,
+       .pointer =      snd_omap_aic23_pointer,
+};
+
+/*
+ *  Alsa init and exit section
+ *  
+ *  Inits pcm alsa structures, allocate the alsa buffer, suspend, resume
+ */
+static int __init snd_card_omap_aic23_pcm(struct snd_card_omap_aic23
+                                         *omap_aic23, int device)
+{
+       snd_pcm_t *pcm;
+       int err;
+       ADEBUG();
+
+       if ((err =
+            snd_pcm_new(omap_aic23->card, "AIC23 PCM", device, 1, 1,
+                        &pcm)) < 0)
+               return err;
+
+       /* sets up initial buffer with continuous allocation */
+       snd_pcm_lib_preallocate_pages_for_all(pcm,
+                                             SNDRV_DMA_TYPE_CONTINUOUS,
+                                             snd_dma_continuous_data
+                                             (GFP_KERNEL),
+                                             128 * 1024, 128 * 1024);
+
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                       &snd_card_omap_aic23_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                       &snd_card_omap_aic23_capture_ops);
+       pcm->private_data = omap_aic23;
+       pcm->info_flags = 0;
+       strcpy(pcm->name, "omap aic23 pcm");
+
+       omap_aic23_audio_init(omap_aic23);
+
+       /* setup DMA controller */
+       audio_dma_request(&omap_aic23->s[SNDRV_PCM_STREAM_PLAYBACK],
+                         audio_dma_callback);
+       audio_dma_request(&omap_aic23->s[SNDRV_PCM_STREAM_CAPTURE],
+                         audio_dma_callback);
+
+       omap_aic23->pcm = pcm;
+
+       return 0;
+}
+
+
+#ifdef CONFIG_PM
+
+static int snd_omap_aic23_suspend(snd_card_t * card, pm_message_t state)
+{
+       struct snd_card_omap_aic23 *chip = card->pm_private_data;
+       ADEBUG();
+
+       if (chip->card->power_state != SNDRV_CTL_POWER_D3hot) {
+               snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
+               snd_pcm_suspend_all(chip->pcm);
+               /* Mutes and turn clock off */
+               omap_aic23_clock_off();
+               snd_omap_suspend_mixer();
+       }
+
+       return 0;
+}
+
+/*
+ *  Prepare hardware for resume
+ */
+static int snd_omap_aic23_resume(snd_card_t * card)
+{
+       struct snd_card_omap_aic23 *chip = card->pm_private_data;
+       ADEBUG();
+       
+       if (chip->card->power_state != SNDRV_CTL_POWER_D0) {
+               snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+               omap_aic23_clock_on();
+               snd_omap_resume_mixer();
+       }
+
+       return 0;
+}
+
+/*
+ * Driver suspend/resume - calls alsa functions. Some hints from aaci.c
+ */
+static int omap_aic23_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+       snd_card_t *card = dev_get_drvdata(dev);
+       
+       if (card->power_state != SNDRV_CTL_POWER_D3hot) {
+               snd_omap_aic23_suspend(card, PMSG_SUSPEND);
+       }
+       return 0;
+}
+
+static int omap_aic23_resume(struct device *dev, u32 level)
+{
+       snd_card_t *card = dev_get_drvdata(dev);
+
+       if (card->power_state != SNDRV_CTL_POWER_D0) {
+               snd_omap_aic23_resume(card);
+       }
+       return 0;
+}
+
+#else
+#define snd_omap_aic23_suspend NULL
+#define snd_omap_aic23_resume  NULL
+#define omap_aic23_suspend     NULL
+#define omap_aic23_resume      NULL
+
+#endif /* CONFIG_PM */
+
+/* 
+ */
+void snd_omap_aic23_free(snd_card_t * card)
+{
+       struct snd_card_omap_aic23 *chip = card->private_data;
+       ADEBUG();
+       
+       /*
+        * Turn off codec after it is done.
+        * Can't do it immediately, since it may still have
+        * buffered data.
+        */
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(2);
+
+       omap_mcbsp_stop(AUDIO_MCBSP);
+       omap_mcbsp_free(AUDIO_MCBSP);
+
+       audio_aic23_write(RESET_CONTROL_ADDR, 0);
+       audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0xff);
+
+       audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
+       audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
+}
+
+/*
+ *  Omap MCBSP clock configuration
+ *  
+ *  Here we have some functions that allows clock to be enabled and
+ *   disabled only when needed. Besides doing clock configuration 
+ *   it allows turn on/turn off audio when necessary. 
+ */
+#define CODEC_CLOCK                   12000000
+#define AUDIO_RATE_DEFAULT           44100
+
+/*
+ * Do clock framework mclk search
+ */
+static __init void omap_aic23_clock_setup(void)
+{
+       aic23_mclk = clk_get(0, "mclk");
+}
+
+/*
+ * Do some sanity check, set clock rate, starts it and
+ *  turn codec audio on 
+ */
+int omap_aic23_clock_on(void)
+{
+       if (clk_get_usecount(aic23_mclk) > 0) {
+               /* MCLK is already in use */
+               printk(KERN_WARNING
+                      "MCLK in use at %d Hz. We change it to %d Hz\n",
+                      (uint) clk_get_rate(aic23_mclk),
+                      CODEC_CLOCK);
+       }
+       
+       if (clk_set_rate(aic23_mclk, CODEC_CLOCK)) {
+               printk(KERN_ERR
+                      "Cannot set MCLK for AIC23 CODEC\n");
+               return -ECANCELED;
+       }
+
+       clk_use(aic23_mclk);
+
+       printk(KERN_DEBUG
+               "MCLK = %d [%d], usecount = %d\n",
+              (uint) clk_get_rate(aic23_mclk), CODEC_CLOCK,
+              clk_get_usecount(aic23_mclk));
+
+       /* Now turn the audio on */
+       audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 
+                         ~DEVICE_POWER_OFF & ~OUT_OFF & ~DAC_OFF &
+                         ~ADC_OFF & ~MIC_OFF & ~LINE_OFF);
+       
+       return 0;
+}
+/*
+ * Do some sanity check, turn clock off and then turn
+ *  codec audio off
+ */
+int omap_aic23_clock_off(void)
+{
+       if  (clk_get_usecount(aic23_mclk) > 0) { 
+               if (clk_get_rate(aic23_mclk) != CODEC_CLOCK) {
+                       printk(KERN_WARNING
+                              "MCLK for audio should be %d Hz. But is %d Hz\n",
+                              (uint) clk_get_rate(aic23_mclk),
+                              CODEC_CLOCK);
+               }
+
+               clk_unuse(aic23_mclk);
+       }
+       
+       audio_aic23_write(POWER_DOWN_CONTROL_ADDR,
+                         DEVICE_POWER_OFF | OUT_OFF | DAC_OFF |
+                         ADC_OFF | MIC_OFF | LINE_OFF);        
+       return 0;
+}
+
+/* module init & exit */
+
+/* 
+ *  Inits alsa soudcard structure
+ */
+static int __init snd_omap_aic23_probe(struct device *dev)
+{
+       int err = 0;
+       snd_card_t *card;
+       ADEBUG();
+       
+       /* gets clock from clock framework */
+       omap_aic23_clock_setup();
+
+       /* register the soundcard */
+       card = snd_card_new(-1, id, THIS_MODULE, sizeof(omap_aic23));
+       if (card == NULL)
+               return -ENOMEM;
+
+       omap_aic23 = kcalloc(1, sizeof(*omap_aic23), GFP_KERNEL);
+       if (omap_aic23 == NULL)
+               return -ENOMEM;
+
+       card->private_data = (void *) omap_aic23;
+       card->private_free = snd_omap_aic23_free;
+
+       omap_aic23->card = card;
+       omap_aic23->samplerate = AUDIO_RATE_DEFAULT;
+
+       spin_lock_init(&omap_aic23->s[0].dma_lock);
+       spin_lock_init(&omap_aic23->s[1].dma_lock);
+
+       /* mixer */
+       if ((err = snd_omap_mixer(omap_aic23)) < 0) 
+               goto nodev;
+
+       /* PCM */
+       if ((err = snd_card_omap_aic23_pcm(omap_aic23, 0)) < 0)
+               goto nodev;
+
+       snd_card_set_pm_callback(card, snd_omap_aic23_suspend,
+                                snd_omap_aic23_resume, omap_aic23);
+
+       strcpy(card->driver, "AIC23");
+       strcpy(card->shortname, "OSK AIC23");
+       sprintf(card->longname, "OMAP OSK with AIC23");
+
+       snd_omap_init_mixer();
+       
+       if ((err = snd_card_register(card)) == 0) {
+               printk(KERN_INFO "OSK audio support initialized\n");
+               dev_set_drvdata(dev, card); 
+               return 0;
+       }
+       
+nodev:
+       snd_omap_aic23_free(card);
+       
+       return err;
+}
+
+static int snd_omap_aic23_remove(struct device *dev)
+{
+       snd_card_t *card = dev_get_drvdata(dev);
+       struct snd_card_omap_aic23 *chip = card->private_data;
+       
+       snd_card_free(card);
+
+       omap_aic23 = NULL;
+       card->private_data = NULL;
+       kfree(chip);
+       
+       dev_set_drvdata(dev, NULL); 
+       
+       return 0;
+       
+}
+
+static struct device_driver omap_alsa_driver = {
+       .name =         "omap_mcbsp",
+       .bus =          &platform_bus_type,
+       .probe =        snd_omap_aic23_probe,
+       .remove =       snd_omap_aic23_remove,
+       .suspend =      omap_aic23_suspend, 
+       .resume =       omap_aic23_resume, 
+};
+
+static int __init omap_aic23_init(void)
+{
+       int err;
+       ADEBUG();
+
+       err = driver_register(&omap_alsa_driver);
+
+       return err;
+}
+
+static void __exit omap_aic23_exit(void)
+{
+       ADEBUG();
+       
+       driver_unregister(&omap_alsa_driver);
+}
+
+module_init(omap_aic23_init);
+module_exit(omap_aic23_exit);
diff --git a/sound/arm/omap-aic23.h b/sound/arm/omap-aic23.h
new file mode 100644 (file)
index 0000000..50b4afb
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * sound/arm/omap-aic23.h
+ * 
+ * Alsa Driver for AIC23 codec on OSK5912 platform board
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by Daniel Petrini, David Cohen, Anderson Briglia
+ *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
+ *
+ * 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.
+ *
+ *  History
+ *  -------
+ *
+ *  2005/07/25 INdT-10LE Kernel Team -         Alsa driver for omap osk,
+ *                                     original version based in sa1100 driver
+ *                                     and omap oss driver.
+ *  
+ */
+
+#ifndef __OMAP_AIC23_H
+#define __OMAP_AIC23_H
+
+#include <sound/driver.h>
+#include <asm/arch/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#define DEFAULT_OUTPUT_VOLUME         0x60
+#define DEFAULT_INPUT_VOLUME          0x00     /* 0 ==> mute line in */
+
+#define OUTPUT_VOLUME_MIN             LHV_MIN
+#define OUTPUT_VOLUME_MAX             LHV_MAX
+#define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
+#define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MAX
+
+#define INPUT_VOLUME_MIN             LIV_MIN
+#define INPUT_VOLUME_MAX             LIV_MAX
+#define INPUT_VOLUME_RANGE           (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
+#define INPUT_VOLUME_MASK            INPUT_VOLUME_MAX
+
+#define SIDETONE_MASK                 0x1c0
+#define SIDETONE_0                    0x100
+#define SIDETONE_6                    0x000
+#define SIDETONE_9                    0x040
+#define SIDETONE_12                   0x080
+#define SIDETONE_18                   0x0c0
+
+#define DEFAULT_ANALOG_AUDIO_CONTROL  DAC_SELECTED | STE_ENABLED | BYPASS_ON | INSEL_MIC | MICB_20DB
+
+/*
+ * Buffer management for alsa and dma
+ */
+struct audio_stream {
+       char *id;               /* identification string */
+       int stream_id;          /* numeric identification */
+       int dma_dev;            /* dma number of that device */
+       int *lch;               /* Chain of channels this stream is linked to */
+       char started;           /* to store if the chain was started or not */
+       int dma_q_head;         /* DMA Channel Q Head */
+       int dma_q_tail;         /* DMA Channel Q Tail */
+       char dma_q_count;       /* DMA Channel Q Count */
+       int active:1;           /* we are using this stream for transfer now */
+       int period;             /* current transfer period */
+       int periods;            /* current count of periods registerd in the DMA engine */
+       spinlock_t dma_lock;    /* for locking in DMA operations */
+       snd_pcm_substream_t *stream;    /* the pcm stream */
+       unsigned linked:1;      /* dma channels linked */
+       int offset;             /* store start position of the last period in the alsa buffer */
+};
+
+/*
+ * Alsa card structure for aic23
+ */
+struct snd_card_omap_aic23 {
+       snd_card_t *card;
+       snd_pcm_t *pcm;
+       long samplerate;
+       struct audio_stream s[2];       /* playback & capture */
+};
+
+/*********** Function Prototypes *************************/
+
+void audio_dma_callback(void *);
+int snd_omap_mixer(struct snd_card_omap_aic23 *);
+void snd_omap_init_mixer(void);
+/* Clock functions */
+int omap_aic23_clock_on(void);
+int omap_aic23_clock_off(void);
+
+#ifdef CONFIG_PM
+void snd_omap_suspend_mixer(void);
+void snd_omap_resume_mixer(void);
+#endif
+
+/* Codec AIC23 */
+#if defined(CONFIG_SENSORS_TLV320AIC23) || defined (CONFIG_SENSORS_TLV320AIC23_MODULE)
+
+extern int tlv320aic23_write_value(u8 reg, u16 value);
+
+/* TLV320AIC23 is a write only device */
+static __inline__ void audio_aic23_write(u8 address, u16 data)
+{
+       tlv320aic23_write_value(address, data);
+}
+
+#endif /* CONFIG_SENSORS_TLV320AIC23 */
+
+#endif
diff --git a/sound/arm/omap-alsa-dma.c b/sound/arm/omap-alsa-dma.c
new file mode 100644 (file)
index 0000000..8d6e9b4
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * sound/arm/omap-alsa-dma.c
+ *
+ * Common audio DMA handling for the OMAP processors
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * 
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004-06-07  Sriram Kannan   - Created new file from omap_audio_dma_intfc.c. This file
+ *                               will contain only the DMA interface and buffer handling of OMAP
+ *                               audio driver.
+ *
+ * 2004-06-22  Sriram Kannan   - removed legacy code (auto-init). Self-linking of DMA logical channel.
+ *
+ * 2004-08-12   Nishanth Menon  - Modified to integrate Audio requirements on 1610,1710 platforms
+ *
+ * 2004-11-01   Nishanth Menon  - 16xx platform code base modified to support multi channel chaining.
+ *
+ * 2004-12-15   Nishanth Menon  - Improved 16xx platform channel logic introduced - tasklets, queue handling updated
+ * 
+ * 2005-07-19  INdT Kernel Team - Alsa port. Creation of new file omap-alsa-dma.c based in
+ *                                omap-audio-dma-intfc.c oss file. Support for aic23 codec.
+ *                                Removal of buffer handling (Alsa does that), modifications
+ *                                in dma handling and port to alsa structures. 
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/sysrq.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+
+#include <asm/arch/dma.h>
+#include "omap-alsa-dma.h"
+
+#include <asm/arch/mcbsp.h>
+
+#include "omap-aic23.h"
+
+#undef DEBUG
+//#define DEBUG
+#ifdef DEBUG
+#define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
+#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
+#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
+#else
+
+#define DPRINTK( x... )
+#define FN_IN
+#define FN_OUT(x)
+#endif
+
+#define ERR(ARGS...) printk(KERN_ERR "{%s}-ERROR: ", __FUNCTION__);printk(ARGS);
+
+/* Channel Queue Handling macros
+ * tail always points to the current free entry
+ * Head always points to the current entry being used
+ * end is either head or tail
+ */
+
+#define AUDIO_QUEUE_INIT(s) s->dma_q_head = s->dma_q_tail = s->dma_q_count = 0;
+#define AUDIO_QUEUE_FULL(s) (nr_linked_channels == s->dma_q_count)
+#define AUDIO_QUEUE_LAST(s) (1 == s->dma_q_count)
+#define AUDIO_QUEUE_EMPTY(s) (0 == s->dma_q_count)
+#define __AUDIO_INCREMENT_QUEUE(end) ((end)=((end)+1) % nr_linked_channels)
+#define AUDIO_INCREMENT_HEAD(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_head); s->dma_q_count--;
+#define AUDIO_INCREMENT_TAIL(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_tail); s->dma_q_count++;
+
+/* DMA buffer fragmentation sizes */
+#define MAX_DMA_SIZE            0x1000000 /* todo: sync with alsa */
+//#define CUT_DMA_SIZE          0x1000
+/* TODO: To be moved to more appropriate location */
+#define DCSR_ERROR           0x3
+#define DCSR_END_BLOCK       (1 << 5)
+#define DCSR_SYNC_SET        (1 << 6)
+
+#define DCCR_FS              (1 << 5)
+#define DCCR_PRIO            (1 << 6)
+#define DCCR_EN              (1 << 7)
+#define DCCR_AI              (1 << 8)
+#define DCCR_REPEAT          (1 << 9)
+/* if 0 the channel works in 3.1 compatible mode*/
+#define DCCR_N31COMP         (1 << 10)
+#define DCCR_EP              (1 << 11)
+#define DCCR_SRC_AMODE_BIT   12
+#define DCCR_SRC_AMODE_MASK  (0x3<<12)
+#define DCCR_DST_AMODE_BIT   14
+#define DCCR_DST_AMODE_MASK  (0x3<<14)
+#define AMODE_CONST          0x0
+#define AMODE_POST_INC       0x1
+#define AMODE_SINGLE_INDEX   0x2
+#define AMODE_DOUBLE_INDEX   0x3
+
+/**************************** DATA STRUCTURES *****************************************/
+
+static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED;
+
+static char nr_linked_channels = 1;
+
+/*********************************** MODULE SPECIFIC FUNCTIONS ***********************/
+
+static void sound_dma_irq_handler(int lch, u16 ch_status, void *data);
+static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
+                                    u_int dma_size);
+static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
+                                       u_int dma_size);
+static int audio_start_dma_chain(struct audio_stream * s);
+
+/***************************************************************************************
+ *
+ * DMA channel requests
+ *
+ **************************************************************************************/
+static void omap_sound_dma_link_lch(void *data)
+{
+
+       struct audio_stream *s = (struct audio_stream *) data;
+       int *chan = s->lch;
+       int i;
+
+       FN_IN;
+       if (s->linked) {
+               FN_OUT(1);
+               return;
+       }
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               int nex_chan =
+                   ((nr_linked_channels - 1 ==
+                     i) ? chan[0] : chan[i + 1]);
+               omap_dma_link_lch(cur_chan, nex_chan);
+       }
+       s->linked = 1;
+       FN_OUT(0);
+}
+
+int omap_request_sound_dma(int device_id, const char *device_name,
+                          void *data, int **channels)
+{
+       int i, err = 0;
+       int *chan = NULL;
+       FN_IN;
+       if (unlikely((NULL == channels) || (NULL == device_name))) {
+               BUG();
+               return -EPERM;
+       }
+       /* Try allocate memory for the num channels */
+       *channels =
+           (int *) kmalloc(sizeof(int) * nr_linked_channels, GFP_KERNEL);
+       chan = *channels;
+       if (NULL == chan) {
+               ERR("No Memory for channel allocs!\n");
+               FN_OUT(-ENOMEM);
+               return -ENOMEM;
+       }
+       spin_lock(&dma_list_lock);
+       for (i = 0; i < nr_linked_channels; i++) {
+               err =
+                   omap_request_dma(device_id, device_name,
+                                    sound_dma_irq_handler, data,
+                                    &chan[i]);
+
+               /* Handle Failure condition here */
+               if (err < 0) {
+                       int j;
+                       for (j = 0; j < i; j++) {
+                               omap_free_dma(chan[j]);
+                       }
+                       spin_unlock(&dma_list_lock);
+                       kfree(chan);
+                       *channels = NULL;
+                       ERR("Error in requesting channel %d=0x%x\n", i,
+                           err);
+                       FN_OUT(err);
+                       return err;
+               }
+       }
+
+       /* Chain the channels together */
+       if (!cpu_is_omap1510())
+               omap_sound_dma_link_lch(data);
+
+       spin_unlock(&dma_list_lock);
+       FN_OUT(0);
+       return 0;
+}
+
+/***************************************************************************************
+ *
+ * DMA channel requests Freeing
+ *
+ **************************************************************************************/
+static void omap_sound_dma_unlink_lch(void *data)
+{
+       struct audio_stream *s = (struct audio_stream *) data;
+       int *chan = s->lch;
+       int i;
+
+       FN_IN;
+       if (!s->linked) {
+               FN_OUT(1);
+               return;
+       }
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               int nex_chan =
+                   ((nr_linked_channels - 1 ==
+                     i) ? chan[0] : chan[i + 1]);
+               omap_dma_unlink_lch(cur_chan, nex_chan);
+       }
+       s->linked = 0;
+       FN_OUT(0);
+}
+
+int omap_free_sound_dma(void *data, int **channels)
+{
+
+       int i;
+       int *chan = NULL;
+       FN_IN;
+       if (unlikely(NULL == channels)) {
+               BUG();
+               return -EPERM;
+       }
+       if (unlikely(NULL == *channels)) {
+               BUG();
+               return -EPERM;
+       }
+       chan = (*channels);
+
+       if (!cpu_is_omap1510())
+               omap_sound_dma_unlink_lch(data);
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               omap_stop_dma(cur_chan);
+               omap_free_dma(cur_chan);
+       }
+       kfree(*channels);
+       *channels = NULL;
+       FN_OUT(0);
+       return 0;
+}
+
+/***************************************************************************************
+ *
+ * Stop all the DMA channels of the stream
+ *
+ **************************************************************************************/
+void omap_audio_stop_dma(struct audio_stream *s)
+{
+       int *chan = s->lch;
+       int i;
+       FN_IN;
+       if (unlikely(NULL == chan)) {
+               BUG();
+               return;
+       }
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               omap_stop_dma(cur_chan);
+       }
+       s->started = 0;
+       FN_OUT(0);
+       return;
+}
+/***************************************************************************************
+ *
+ * Clear any pending transfers
+ *
+ **************************************************************************************/
+void omap_clear_sound_dma(struct audio_stream * s)
+{
+       FN_IN;
+       omap_clear_dma(s->lch[s->dma_q_head]);
+       FN_OUT(0);
+       return;
+}
+
+/*********************************** MODULE FUNCTIONS DEFINTIONS ***********************/
+
+#ifdef OMAP1610_MCBSP1_BASE
+#undef OMAP1610_MCBSP1_BASE
+#endif
+#define OMAP1610_MCBSP1_BASE    0xE1011000
+
+/***************************************************************************************
+ *
+ * DMA related functions
+ *
+ **************************************************************************************/
+static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
+                                    u_int dma_size)
+{
+       int dt = 0x1;           /* data type 16 */
+       int cen = 32;           /* Stereo */
+       int cfn = dma_size / (2 * cen);
+       FN_IN;
+       omap_set_dma_dest_params(channel, 0x05, 0x00,
+                                (OMAP1610_MCBSP1_BASE + 0x806),
+                                0, 0);
+       omap_set_dma_src_params(channel, 0x00, 0x01, dma_ptr,
+                               0, 0);
+       omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
+       FN_OUT(0);
+       return 0;
+}
+
+static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
+                                       u_int dma_size)
+{
+       int dt = 0x1;           /* data type 16 */
+       int cen = 32;           /* stereo */
+       
+       int cfn = dma_size / (2 * cen);
+       FN_IN;
+       omap_set_dma_src_params(channel, 0x05, 0x00,
+                               (OMAP1610_MCBSP1_BASE + 0x802),
+                               0, 0);
+       omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr, 0, 0);
+       omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
+       FN_OUT(0);
+       return 0;
+}
+
+static int audio_start_dma_chain(struct audio_stream *s)
+{
+       int channel = s->lch[s->dma_q_head];
+       FN_IN;
+       if (!s->started) {
+               omap_start_dma(channel);
+               s->started = 1;
+       }
+       /* else the dma itself will progress forward with out our help */
+       FN_OUT(0);
+       return 0;
+}
+
+/* Start DMA -
+ * Do the initial set of work to initialize all the channels as required.
+ * We shall then initate a transfer
+ */
+int omap_start_sound_dma(struct audio_stream *s, dma_addr_t dma_ptr,
+                        u_int dma_size)
+{
+       int ret = -EPERM;
+
+       FN_IN;
+
+       if (unlikely(dma_size > MAX_DMA_SIZE)) {
+               ERR("DmaSoundDma: Start: overflowed %d-%d\n", dma_size,
+                   MAX_DMA_SIZE);
+               return -EOVERFLOW;
+       }
+       //if (AUDIO_QUEUE_FULL(s)) {
+       //      ret = -2;
+       //      goto sound_out;
+       //}
+
+       if (s->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
+               /*playback */
+               ret =
+                   audio_set_dma_params_play(s->lch[s->dma_q_tail],
+                                             dma_ptr, dma_size);
+       } else {
+               ret =
+                   audio_set_dma_params_capture(s->lch[s->dma_q_tail],
+                                                dma_ptr, dma_size);
+       }
+       if (ret != 0) {
+               ret = -3;       /* indicate queue full */
+               goto sound_out;
+       }
+       AUDIO_INCREMENT_TAIL(s);
+       ret = audio_start_dma_chain(s);
+       if (ret) {
+               ERR("dma start failed");
+       }
+      sound_out:
+       FN_OUT(ret);
+       return ret;
+
+}
+
+/* 
+ * ISRs have to be short and smart.. 
+ * Here we call alsa handling, after some error checking
+ */
+static void sound_dma_irq_handler(int sound_curr_lch, u16 ch_status,
+                                 void *data)
+{
+       int dma_status = ch_status;
+       struct audio_stream *s = (struct audio_stream *) data;
+       FN_IN;
+
+       /*
+        * some register checkings
+        */ 
+       DPRINTK("lch=%d,status=0x%x, dma_status=%d, data=%p\n",
+               sound_curr_lch, ch_status, dma_status, data);
+
+       if (dma_status & (DCSR_ERROR)) {
+               OMAP_DMA_CCR_REG(sound_curr_lch) &= ~DCCR_EN;
+               ERR("DCSR_ERROR!\n");
+               FN_OUT(-1);
+               return;
+       }
+
+       if (ch_status & DCSR_END_BLOCK) 
+               audio_dma_callback(s);
+       FN_OUT(0);
+       return;
+}
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION
+    ("Common DMA handling for Audio driver on OMAP processors");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(omap_start_sound_dma);
+EXPORT_SYMBOL(omap_clear_sound_dma);
+EXPORT_SYMBOL(omap_request_sound_dma);
+EXPORT_SYMBOL(omap_free_sound_dma);
+EXPORT_SYMBOL(omap_audio_stop_dma);
diff --git a/sound/arm/omap-alsa-dma.h b/sound/arm/omap-alsa-dma.h
new file mode 100644 (file)
index 0000000..2ac7650
--- /dev/null
@@ -0,0 +1,59 @@
+/*  
+ * linux/sound/arm/omap-alsa-dma.h
+ *
+ * Common audio DMA handling for the OMAP processors
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * 
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 
+ * 2004/08/12  Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms
+ *
+ * 2005/07/25  INdT Kernel Team - Renamed to omap-alsa-dma.h. Ported to Alsa.
+ */
+
+#ifndef __OMAP_AUDIO_ALSA_DMA_H
+#define __OMAP_AUDIO_ALSA_DMA_H
+
+/************************** INCLUDES *************************************/
+
+#include "omap-aic23.h"
+
+/************************** GLOBAL MACROS *************************************/
+
+/* Provide the Macro interfaces common across platforms */
+#define DMA_REQUEST(e,s, cb)   {e=omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);}
+#define DMA_FREE(s)            omap_free_sound_dma(s, &s->lch)
+#define DMA_CLEAR(s)           omap_clear_sound_dma(s)
+
+/************************** GLOBAL DATA STRUCTURES *********************************/
+
+typedef void (*dma_callback_t) (int lch, u16 ch_status, void *data);
+
+/**************** ARCH SPECIFIC FUNCIONS *******************************************/
+
+void omap_clear_sound_dma(struct audio_stream * s);
+
+int omap_request_sound_dma(int device_id, const char *device_name,
+                          void *data, int **channels);
+int omap_free_sound_dma(void *data, int **channels);
+
+int omap_start_sound_dma(struct audio_stream *s, dma_addr_t dma_ptr,
+                        u_int dma_size);
+
+void omap_audio_stop_dma(struct audio_stream *s);
+
+#endif
diff --git a/sound/arm/omap-alsa-mixer.c b/sound/arm/omap-alsa-mixer.c
new file mode 100644 (file)
index 0000000..742e5b6
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * sound/arm/omap-alsa-mixer.c
+ * 
+ * Alsa Driver Mixer for generic codecs for omap boards
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by David Cohen, Daniel Petrini
+ *            {david.cohen, daniel.petrini}@indt.org.br
+ *
+ * Based on es1688_lib.c, 
+ * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *  
+ * 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.
+ *
+ * History:
+ *
+ * 2005-08-02   INdT Kernel Team - Alsa mixer driver for omap osk. Creation of new 
+ *                                 file omap-alsa-mixer.c. Initial version
+ *                                 with aic23 codec for osk5912
+ */
+
+#include <linux/config.h>
+#include <sound/driver.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/aic23.h>
+
+#include "omap-aic23.h"
+#include <sound/initval.h>
+#include <sound/control.h>
+
+MODULE_AUTHOR("David Cohen, Daniel Petrini - INdT");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("OMAP Alsa mixer driver for ALSA");
+
+/*
+ * Codec dependent region
+ */
+
+/* Codec AIC23 */
+#if defined(CONFIG_SENSORS_TLV320AIC23) || defined (CONFIG_SENSORS_TLV320AIC23_MODULE)
+
+extern __inline__ void audio_aic23_write(u8, u16);
+
+#define MIXER_NAME                  "Mixer AIC23"
+#define SND_OMAP_WRITE(reg, val)     audio_aic23_write(reg, val)
+
+#endif
+
+/* Callback Functions */
+#define OMAP_BOOL(xname, xindex, reg, reg_index, mask, invert) \
+{ \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_omap_info_bool, \
+       .get = snd_omap_get_bool, \
+       .put = snd_omap_put_bool, \
+       .private_value = reg | (reg_index << 8) | (invert << 10) | (mask << 12) \
+}
+
+#define OMAP_MUX(xname, reg, reg_index, mask) \
+{ \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .info = snd_omap_info_mux, \
+       .get = snd_omap_get_mux, \
+       .put = snd_omap_put_mux, \
+       .private_value = reg | (reg_index << 8) | (mask << 10) \
+}
+
+#define OMAP_SINGLE(xname, xindex, reg, reg_index, reg_val, mask) \
+{\
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_omap_info_single, \
+       .get = snd_omap_get_single, \
+       .put = snd_omap_put_single, \
+       .private_value = reg | (reg_val << 8) | (reg_index << 16) | (mask << 18) \
+}
+
+#define OMAP_DOUBLE(xname, xindex, left_reg, right_reg, reg_index, mask) \
+{\
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_omap_info_double, \
+       .get = snd_omap_get_double, \
+       .put = snd_omap_put_double, \
+       .private_value = left_reg | (right_reg << 8) | (reg_index << 16) | (mask << 18) \
+}
+
+/* Local Registers */
+enum snd_device_index {
+       PCM_INDEX = 0,
+       LINE_INDEX,
+       AAC_INDEX, /* Analog Audio Control: reg = l_reg */
+};
+
+struct {
+       u16 l_reg;
+       u16 r_reg;
+       u8 sw;
+} omap_regs[3];
+
+#ifdef CONFIG_PM
+struct {
+       u16 l_reg;
+       u16 r_reg;
+       u8 sw;
+} omap_pm_regs[3];
+#endif
+
+u16 snd_sidetone[6] = {
+       SIDETONE_18,
+       SIDETONE_12,
+       SIDETONE_9,
+       SIDETONE_6,
+       SIDETONE_0,
+       0
+};
+
+/* Begin Bool Functions */
+
+static int snd_omap_info_bool(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       
+       return 0;
+}
+
+static int snd_omap_get_bool(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       int mic_index = (kcontrol->private_value >> 8) & 0x03;
+       u16 mask = (kcontrol->private_value >> 12) & 0xff;
+       int invert = (kcontrol->private_value >> 10) & 0x03;
+       
+       if (invert)
+               ucontrol->value.integer.value[0] = (omap_regs[mic_index].l_reg & mask) ? 0 : 1;
+       else
+               ucontrol->value.integer.value[0] = (omap_regs[mic_index].l_reg & mask) ? 1 : 0;
+       
+       return 0;
+}
+
+static int snd_omap_put_bool(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       int mic_index = (kcontrol->private_value >> 8) & 0x03;
+       u16 mask = (kcontrol->private_value >> 12) & 0xff;
+       u16 reg = kcontrol->private_value & 0xff;
+       int invert = (kcontrol->private_value >> 10) & 0x03;
+       
+       int changed = 1;
+
+       if (ucontrol->value.integer.value[0]) /* XOR */
+               if (invert)
+                       omap_regs[mic_index].l_reg &= ~mask;
+               else
+                       omap_regs[mic_index].l_reg |= mask;
+       else
+               if (invert)
+                       omap_regs[mic_index].l_reg |= mask;
+               else
+                       omap_regs[mic_index].l_reg &= ~mask;
+               
+       SND_OMAP_WRITE(reg, omap_regs[mic_index].l_reg);
+       
+       return changed;
+}
+
+/* End Bool Functions */
+
+/* Begin Mux Functions */
+
+static int snd_omap_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       /* Mic = 0
+        * Line = 1 */
+       static char *texts[2] = { "Mic", "Line" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       
+       if (uinfo->value.enumerated.item > 1)
+               uinfo->value.enumerated.item = 1;
+       
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       
+       return 0;
+}
+
+static int snd_omap_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       u16 mask = (kcontrol->private_value >> 10) & 0xff;
+       int mux_index = (kcontrol->private_value >> 8) & 0x03;
+
+       ucontrol->value.enumerated.item[0] = (omap_regs[mux_index].l_reg & mask) ? 0 /* Mic */ : 1 /* Line */;
+       
+       return 0;
+}
+
+static int snd_omap_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       u16 reg = kcontrol->private_value & 0xff;
+       u16 mask = (kcontrol->private_value >> 10) & 0xff;
+       int mux_index = (kcontrol->private_value >> 8) & 0x03;
+       
+       int changed = 1;
+
+       if (!ucontrol->value.integer.value[0])
+               omap_regs[mux_index].l_reg |= mask; /* AIC23: Mic */
+       else
+               omap_regs[mux_index].l_reg &= ~mask; /* AIC23: Line */
+       
+       SND_OMAP_WRITE(reg, omap_regs[mux_index].l_reg);
+       
+       return changed;
+}
+
+/* End Mux Functions */
+
+/* Begin Single Functions */
+
+static int snd_omap_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       int mask = (kcontrol->private_value >> 18) & 0xff;
+       int reg_val = (kcontrol->private_value >> 8) & 0xff;
+       
+       uinfo->type = mask ? SNDRV_CTL_ELEM_TYPE_INTEGER : SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = reg_val-1;
+       
+       return 0;
+}
+
+static int snd_omap_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       u16 reg_val = (kcontrol->private_value >> 8) & 0xff;
+
+       ucontrol->value.integer.value[0] = snd_sidetone[reg_val];
+       
+       return 0;
+}
+
+static int snd_omap_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       u16 reg_index = (kcontrol->private_value >> 16) & 0x03;
+       u16 mask = (kcontrol->private_value >> 18) & 0x1ff;
+       u16 reg = kcontrol->private_value & 0xff;
+       u16 reg_val = (kcontrol->private_value >> 8) & 0xff;
+
+       int changed = 0;
+
+       /* Volume */
+       if ((omap_regs[reg_index].l_reg != (ucontrol->value.integer.value[0] & mask)))
+       {
+               changed = 1;
+       
+               omap_regs[reg_index].l_reg &= ~mask;
+               omap_regs[reg_index].l_reg |= snd_sidetone[ucontrol->value.integer.value[0]];
+
+               snd_sidetone[reg_val] = ucontrol->value.integer.value[0];
+               SND_OMAP_WRITE(reg, omap_regs[reg_index].l_reg);
+       }
+       else
+               changed = 0;
+       
+       return changed;
+}
+
+/* End Single Functions */
+
+/* Begin Double Functions */
+
+static int snd_omap_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       /* mask == 0 : Switch
+        * mask != 0 : Volume */
+       int mask = (kcontrol->private_value >> 18) & 0xff;
+
+       uinfo->type = mask ? SNDRV_CTL_ELEM_TYPE_INTEGER : SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = mask ? 2 : 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = mask ? mask : 1;
+       
+       return 0;
+}
+
+static int snd_omap_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       /* mask == 0 : Switch
+        * mask != 0 : Volume */
+       int mask = (kcontrol->private_value >> 18) & 0xff;
+       int vol_index = (kcontrol->private_value >> 16) & 0x03;
+       
+       if (!mask)
+               /* Switch */
+               ucontrol->value.integer.value[0] = omap_regs[vol_index].sw;
+       else
+       {
+               /* Volume */
+               ucontrol->value.integer.value[0] = omap_regs[vol_index].l_reg;
+               ucontrol->value.integer.value[1] = omap_regs[vol_index].r_reg;
+       }
+
+       return 0;
+}
+
+static int snd_omap_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       /* mask == 0 : Switch
+        * mask != 0 : Volume */
+       int vol_index = (kcontrol->private_value >> 16) & 0x03;
+       int mask = (kcontrol->private_value >> 18) & 0xff;
+       int left_reg = kcontrol->private_value & 0xff;
+       int right_reg = (kcontrol->private_value >> 8) & 0xff;
+
+       int changed = 0;
+
+       if (!mask)
+       {
+               /* Switch */
+               if (!ucontrol->value.integer.value[0])
+               {
+                       SND_OMAP_WRITE(left_reg, 0x00);
+                       SND_OMAP_WRITE(right_reg, 0x00);
+               }
+               else
+               {
+                       SND_OMAP_WRITE(left_reg, omap_regs[vol_index].l_reg);
+                       SND_OMAP_WRITE(right_reg, omap_regs[vol_index].r_reg);
+               }
+               changed = 1;
+               omap_regs[vol_index].sw = ucontrol->value.integer.value[0]; 
+       }
+       else
+       {
+               /* Volume */
+               if ((omap_regs[vol_index].l_reg != (ucontrol->value.integer.value[0] & mask)) ||
+                   (omap_regs[vol_index].r_reg != (ucontrol->value.integer.value[1] & mask)))
+               {
+                       changed = 1;
+               
+                       omap_regs[vol_index].l_reg &= ~mask;
+                       omap_regs[vol_index].r_reg &= ~mask;
+                       omap_regs[vol_index].l_reg |= (ucontrol->value.integer.value[0] & mask);
+                       omap_regs[vol_index].r_reg |= (ucontrol->value.integer.value[1] & mask);
+                       if (omap_regs[vol_index].sw)
+                       {
+                               /* write to registers only if sw is actived */
+                               SND_OMAP_WRITE(left_reg, omap_regs[vol_index].l_reg);
+                               SND_OMAP_WRITE(right_reg, omap_regs[vol_index].r_reg);
+                       }
+               }
+               else
+                       changed = 0;
+       }
+       
+       return changed;
+}
+
+/* End Double Functions */
+
+static snd_kcontrol_new_t snd_omap_controls[] = {
+       OMAP_DOUBLE("PCM Playback Switch", 0, LEFT_CHANNEL_VOLUME_ADDR, RIGHT_CHANNEL_VOLUME_ADDR,
+                    PCM_INDEX, 0x00),
+       OMAP_DOUBLE("PCM Playback Volume", 0, LEFT_CHANNEL_VOLUME_ADDR, RIGHT_CHANNEL_VOLUME_ADDR,
+                    PCM_INDEX, OUTPUT_VOLUME_MASK),
+       OMAP_BOOL("Line Playback Switch", 0, ANALOG_AUDIO_CONTROL_ADDR, AAC_INDEX, BYPASS_ON, 0),
+       OMAP_DOUBLE("Line Capture Switch", 0, LEFT_LINE_VOLUME_ADDR, RIGHT_LINE_VOLUME_ADDR,
+                    LINE_INDEX, 0x00),
+       OMAP_DOUBLE("Line Capture Volume", 0, LEFT_LINE_VOLUME_ADDR, RIGHT_LINE_VOLUME_ADDR,
+                    LINE_INDEX, INPUT_VOLUME_MASK),    
+       OMAP_BOOL("Mic Playback Switch", 0, ANALOG_AUDIO_CONTROL_ADDR, AAC_INDEX, STE_ENABLED, 0),      
+       OMAP_SINGLE("Mic Playback Volume", 0, ANALOG_AUDIO_CONTROL_ADDR, AAC_INDEX, 5, SIDETONE_MASK),
+       OMAP_BOOL("Mic Capture Switch", 0, ANALOG_AUDIO_CONTROL_ADDR, AAC_INDEX, MICM_MUTED, 1),
+       OMAP_BOOL("Mic Booster Playback Switch", 0, ANALOG_AUDIO_CONTROL_ADDR, AAC_INDEX, MICB_20DB, 0),
+       OMAP_MUX("Capture Source", ANALOG_AUDIO_CONTROL_ADDR, AAC_INDEX, INSEL_MIC),
+};
+
+void snd_omap_init_mixer(void)
+{
+       u16 vol_reg;
+
+       /* Line's default values */
+       omap_regs[LINE_INDEX].l_reg = DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK;
+       omap_regs[LINE_INDEX].r_reg = DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK;
+       omap_regs[LINE_INDEX].sw = 0;
+       SND_OMAP_WRITE(LEFT_LINE_VOLUME_ADDR, DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK);
+       SND_OMAP_WRITE(RIGHT_LINE_VOLUME_ADDR, DEFAULT_INPUT_VOLUME & INPUT_VOLUME_MASK);
+       
+       /* Analog Audio Control's default values */
+       omap_regs[AAC_INDEX].l_reg = DEFAULT_ANALOG_AUDIO_CONTROL;
+       
+       /* Headphone's default values */
+       vol_reg = LZC_ON;
+       vol_reg &= ~OUTPUT_VOLUME_MASK;
+       vol_reg |= DEFAULT_OUTPUT_VOLUME;
+       omap_regs[PCM_INDEX].l_reg = DEFAULT_OUTPUT_VOLUME;
+       omap_regs[PCM_INDEX].r_reg = DEFAULT_OUTPUT_VOLUME;
+       omap_regs[PCM_INDEX].sw = 1;
+       SND_OMAP_WRITE(LEFT_CHANNEL_VOLUME_ADDR, vol_reg);
+       SND_OMAP_WRITE(RIGHT_CHANNEL_VOLUME_ADDR, vol_reg);
+}
+
+#ifdef CONFIG_PM
+
+void snd_omap_suspend_mixer(void)
+{
+       /* Saves current values to wake-up correctly */
+       omap_pm_regs[LINE_INDEX].l_reg = omap_regs[LINE_INDEX].l_reg;
+       omap_pm_regs[LINE_INDEX].r_reg = omap_regs[LINE_INDEX].l_reg;
+       omap_pm_regs[LINE_INDEX].sw = omap_regs[LINE_INDEX].sw;
+       
+       omap_pm_regs[AAC_INDEX].l_reg = omap_regs[AAC_INDEX].l_reg;
+       
+       omap_pm_regs[PCM_INDEX].l_reg = omap_regs[PCM_INDEX].l_reg;
+       omap_pm_regs[PCM_INDEX].r_reg = omap_regs[PCM_INDEX].r_reg;
+       omap_pm_regs[PCM_INDEX].sw = omap_regs[PCM_INDEX].sw;
+}
+
+void snd_omap_resume_mixer(void)
+{
+       /* Line's saved values */
+       omap_regs[LINE_INDEX].l_reg = omap_pm_regs[LINE_INDEX].l_reg;
+       omap_regs[LINE_INDEX].r_reg = omap_pm_regs[LINE_INDEX].l_reg;
+       omap_regs[LINE_INDEX].sw = omap_pm_regs[LINE_INDEX].sw;
+       SND_OMAP_WRITE(LEFT_LINE_VOLUME_ADDR, omap_pm_regs[LINE_INDEX].l_reg);
+       SND_OMAP_WRITE(RIGHT_LINE_VOLUME_ADDR, omap_pm_regs[LINE_INDEX].l_reg);
+       
+       /* Analog Audio Control's saved values */
+       omap_regs[AAC_INDEX].l_reg = omap_pm_regs[AAC_INDEX].l_reg;
+       SND_OMAP_WRITE(ANALOG_AUDIO_CONTROL_ADDR, omap_regs[AAC_INDEX].l_reg);
+       
+       /* Headphone's saved values */
+       omap_regs[PCM_INDEX].l_reg = omap_pm_regs[PCM_INDEX].l_reg;
+       omap_regs[PCM_INDEX].r_reg = omap_pm_regs[PCM_INDEX].r_reg;
+       omap_regs[PCM_INDEX].sw = omap_pm_regs[PCM_INDEX].sw;
+       SND_OMAP_WRITE(LEFT_CHANNEL_VOLUME_ADDR, omap_pm_regs[PCM_INDEX].l_reg);
+       SND_OMAP_WRITE(RIGHT_CHANNEL_VOLUME_ADDR, omap_pm_regs[PCM_INDEX].r_reg);
+}
+#endif
+
+int snd_omap_mixer(struct snd_card_omap_aic23 *chip)
+{
+       snd_card_t *card;
+       unsigned int idx;
+       int err;
+
+       snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
+
+       card = chip->card;
+
+       strcpy(card->mixername, MIXER_NAME);
+
+       /* Registering alsa mixer controls */
+       for (idx = 0; idx < ARRAY_SIZE(snd_omap_controls); idx++) 
+               if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_omap_controls[idx], chip))) < 0)
+                       return err;
+
+       return 0;
+}
+
index 88e52dc84c096b94514fd2e4ed76761edaceb42a..0eb23d3b73f38f113945a45ec2f2642bc276da8a 100644 (file)
@@ -4,24 +4,34 @@
 # More hacking for modularisation.
 #
 # Prompt user for primary drivers.
+config SOUND_OMAP
+       tristate "OMAP Sound Driver"
+       depends on SOUND_PRIME!=n && SOUND && ARCH_OMAP
+       ---help---
+         OMAP Audio driver
 
-config OBSOLETE_OSS_DRIVER
-       bool "Obsolete OSS drivers"
-       depends on SOUND_PRIME
-       help
-         This option enables support for obsolete OSS drivers that
-         are scheduled for removal in the near future since there
-         are ALSA drivers for the same hardware.
-
-         Please contact Adrian Bunk <bunk@stusta.de> if you had to
-         say Y here because your soundcard is not properly supported
-         by ALSA.
-
-         If unsure, say N.
+config SOUND_OMAP_TSC2101
+       tristate "TSC2101 Stereo Codec"
+       depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 )
+       select OMAP_TSC2101
+       select OMAP_UWIRE if ARCH_OMAP
+       ---help---
+         Tsc2101 Audio Codec Driver for OMAP will be enabled.
+         Will also Enable the following:
+         1. uWire Driver based on Platform
+         2. TSC2101 Glue driver
+
+config SOUND_OMAP_AIC23
+       tristate "AIC23 Stereo Codec"
+       depends on SOUND_OMAP && ( MACH_OMAP_INNOVATOR || MACH_OMAP_OSK )
+       select SENSORS_TLV320AIC23 if ARCH_OMAP
+       ---help---
+         AIC23 Audio Codec Driver for OMAP will be enabled.
+         Additionally, AIC23 I2C support is enabled.
 
 config SOUND_BT878
        tristate "BT878 audio dma"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        ---help---
          Audio DMA support for bt878 based grabber boards.  As you might have
          already noticed, bt878 is listed with two functions in /proc/pci.
@@ -37,7 +47,7 @@ config SOUND_BT878
 
 config SOUND_CMPCI
        tristate "C-Media PCI (CMI8338/8738)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card using the CMI8338
          or the CMI8738 chipset.  Data on these chips are available at
@@ -76,7 +86,7 @@ config SOUND_CMPCI_JOYSTICK
 
 config SOUND_EMU10K1
        tristate "Creative SBLive! (EMU10K1)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        ---help---
          Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
          such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -110,7 +120,7 @@ config SOUND_FUSION
 
 config SOUND_CS4281
        tristate "Crystal Sound CS4281"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Picture and feature list at
          <http://www.pcbroker.com/crystal4281.html>.
@@ -127,7 +137,7 @@ config SOUND_BCM_CS4297A
 
 config SOUND_ES1370
        tristate "Ensoniq AudioPCI (ES1370)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the Ensoniq
          ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
@@ -140,7 +150,7 @@ config SOUND_ES1370
 
 config SOUND_ES1371
        tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the Ensoniq
          ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -153,7 +163,7 @@ config SOUND_ES1371
 
 config SOUND_ESSSOLO1
        tristate "ESS Technology Solo1" 
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the ESS Technology
          Solo1 chip. To find out if your sound card uses a
@@ -164,7 +174,7 @@ config SOUND_ESSSOLO1
 
 config SOUND_MAESTRO
        tristate "ESS Maestro, Maestro2, Maestro2E driver"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a sound system driven by ESS's Maestro line
          of PCI sound chips.  These include the Maestro 1, Maestro 2, and
@@ -173,7 +183,7 @@ config SOUND_MAESTRO
 
 config SOUND_MAESTRO3
        tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
-       depends on SOUND_PRIME && PCI && EXPERIMENTAL && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI && EXPERIMENTAL
        help
          Say Y or M if you have a sound system driven by ESS's Maestro 3
          PCI sound chip.
@@ -187,14 +197,14 @@ config SOUND_ICH
 
 config SOUND_HARMONY
        tristate "PA Harmony audio driver"
-       depends on GSC_LASI && SOUND_PRIME && OBSOLETE_OSS_DRIVER
+       depends on GSC_LASI && SOUND_PRIME
        help
          Say 'Y' or 'M' to include support for Harmony soundchip
          on HP 712, 715/new and many other GSC based machines.
 
 config SOUND_SONICVIBES
        tristate "S3 SonicVibes"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the S3
          SonicVibes chipset. To find out if your sound card uses a
@@ -233,7 +243,7 @@ config SOUND_VRC5477
 
 config SOUND_AU1000
        tristate "Au1000 Sound"
-       depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500)
 
 config SOUND_AU1550_AC97
        tristate "Au1550 AC97 Sound"
@@ -507,7 +517,7 @@ config MSND_FIFOSIZE
 
 config SOUND_VIA82CXXX
        tristate "VIA 82C686 Audio Codec"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y here to include support for the audio codec found on VIA
          82Cxxx-based chips. Typically these are built into a motherboard.
@@ -578,7 +588,7 @@ config SOUND_AD1889
 
 config SOUND_SGALAXY
        tristate "Aztech Sound Galaxy (non-PnP) cards"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          This module initializes the older non Plug and Play sound galaxy
          cards from Aztech. It supports the Waverider Pro 32 - 3D and the
@@ -614,7 +624,7 @@ config SOUND_ACI_MIXER
 
 config SOUND_CS4232
        tristate "Crystal CS4232 based (PnP) cards"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Say Y here if you have a card based on the Crystal CS4232 chip set,
          which uses its own Plug and Play protocol.
@@ -628,7 +638,7 @@ config SOUND_CS4232
 
 config SOUND_SSCAPE
        tristate "Ensoniq SoundScape support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Answer Y if you have a sound card based on the Ensoniq SoundScape
          chipset. Such cards are being manufactured at least by Ensoniq, Spea
@@ -640,7 +650,7 @@ config SOUND_SSCAPE
 
 config SOUND_GUS
        tristate "Gravis Ultrasound support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Say Y here for any type of Gravis Ultrasound card, including the GUS
          or GUS MAX.  See also <file:Documentation/sound/oss/ultrasound> for more
@@ -742,7 +752,7 @@ config SOUND_MPU401
 
 config SOUND_NM256
        tristate "NM256AV/NM256ZX audio support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Say M here to include audio support for the NeoMagic 256AV/256ZX
          chipsets. These are the audio chipsets found in the Sony
@@ -754,7 +764,7 @@ config SOUND_NM256
 
 config SOUND_MAD16
        tristate "OPTi MAD16 and/or Mozart based cards"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        ---help---
          Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
          82C928 or 82C929 or 82C931) audio interface chip. These chips are
@@ -875,7 +885,7 @@ config SOUND_SB
 
 config SOUND_AWE32_SYNTH
        tristate "AWE32 synth"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
          similar sound card. See <file:Documentation/sound/oss/README.awe>,
@@ -885,7 +895,7 @@ config SOUND_AWE32_SYNTH
 
 config SOUND_WAVEFRONT
        tristate "Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards"
-       depends on SOUND_OSS && m && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS && m
        help
          Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
          and read the files <file:Documentation/sound/oss/Wavefront> and
@@ -893,7 +903,7 @@ config SOUND_WAVEFRONT
 
 config SOUND_MAUI
        tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
          sound card.
@@ -919,7 +929,7 @@ config MAUI_BOOT_FILE
 
 config SOUND_YM3812
        tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        ---help---
          Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
          Answering Y is usually a safe and recommended choice, however some
@@ -935,7 +945,7 @@ config SOUND_YM3812
 
 config SOUND_OPL3SA1
        tristate "Yamaha OPL3-SA1 audio controller"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
          usually built into motherboards. Read
@@ -961,7 +971,7 @@ config SOUND_OPL3SA2
 
 config SOUND_YMFPCI
        tristate "Yamaha YMF7xx PCI audio (native mode)"
-       depends on SOUND_OSS && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS && PCI
        help
          Support for Yamaha cards including the YMF711, YMF715, YMF718,
          YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital.
@@ -1103,11 +1113,11 @@ config SOUND_KAHLUA
 
 config SOUND_ALI5455
        tristate "ALi5455 audio support"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
 
 config SOUND_FORTE
        tristate "ForteMedia FM801 driver"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you want driver support for the ForteMedia FM801 PCI
          audio controller (Abit AU10, Genius Sound Maker, HP Workstation
@@ -1115,7 +1125,7 @@ config SOUND_FORTE
 
 config SOUND_RME96XX
        tristate "RME Hammerfall (RME96XX) support"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a Hammerfall or Hammerfall light
          multichannel card from RME. If you want to access advanced
@@ -1123,7 +1133,7 @@ config SOUND_RME96XX
 
 config SOUND_AD1980
        tristate "AD1980 front/back switch plugin"
-       depends on SOUND_PRIME && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME
 
 config SOUND_SH_DAC_AUDIO
        tristate "SuperH DAC audio support"
index 9bf3ee544d86e62987c2d23e20bea83b5bfcd0c2..17ca39dfe0082b2d7e1ca051c8bc211ddb4f7e67 100644 (file)
@@ -8,6 +8,10 @@
 obj-$(CONFIG_SOUND_OSS)                += sound.o
 obj-$(CONFIG_SOUND_CS4232)     += cs4232.o ad1848.o 
 
+obj-$(CONFIG_SOUND_OMAP)        += omap-audio-dma-intfc.o omap-audio.o
+obj-$(CONFIG_SOUND_OMAP_TSC2101)+= omap-audio-tsc2101.o
+obj-$(CONFIG_SOUND_OMAP_AIC23)  += omap-audio-aic23.o
+
 # Please leave it as is, cause the link order is significant !
 
 obj-$(CONFIG_SOUND_SH_DAC_AUDIO)       += sh_dac_audio.o
diff --git a/sound/oss/omap-audio-aic23.c b/sound/oss/omap-audio-aic23.c
new file mode 100644 (file)
index 0000000..d58c6f5
--- /dev/null
@@ -0,0 +1,733 @@
+/*
+ * linux/sound/oss/omap-audio-aic23.c
+ *
+ * Glue audio driver for TI TLV320AIC23 codec
+ *
+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 2001, Steve Johnson <stevej@ridgerun.com>
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2005 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/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/aic23.h>
+
+#include <asm/hardware/clock.h>
+
+#include "omap-audio.h"
+#include "omap-audio-dma-intfc.h"
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#define PROC_START_FILE "driver/aic23-audio-start"
+#define PROC_STOP_FILE  "driver/aic23-audio-stop"
+#endif
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTK(ARGS...)  printk("<%s>: ",__FUNCTION__);printk(ARGS)
+#else
+#define DPRINTK( x... )
+#endif
+
+#define CODEC_NAME              "AIC23"
+
+#if CONFIG_MACH_OMAP_OSK
+#define PLATFORM_NAME            "OMAP OSK"
+#elif CONFIG_MACH_OMAP_INNOVATOR
+#define PLATFORM_NAME            "OMAP INNOVATOR"
+#else
+#error "Unsupported plattform"
+#endif
+
+/* Define to set the AIC23 as the master w.r.t McBSP */
+#define AIC23_MASTER
+
+#define CODEC_CLOCK                   12000000
+
+/*
+ * AUDIO related MACROS
+ */
+#define DEFAULT_BITPERSAMPLE          16
+#define AUDIO_RATE_DEFAULT           44100
+
+/* Select the McBSP For Audio */
+#define AUDIO_MCBSP                   OMAP_MCBSP1
+
+#define REC_MASK                     (SOUND_MASK_LINE | SOUND_MASK_MIC)
+#define DEV_MASK                     (REC_MASK | SOUND_MASK_VOLUME)
+
+#define SET_VOLUME                   1
+#define SET_LINE                     2
+
+#define DEFAULT_OUTPUT_VOLUME         93
+#define DEFAULT_INPUT_VOLUME          0        /* 0 ==> mute line in */
+
+#define OUTPUT_VOLUME_MIN             LHV_MIN
+#define OUTPUT_VOLUME_MAX             LHV_MAX
+#define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
+#define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MAX
+
+#define INPUT_VOLUME_MIN             LIV_MIN
+#define INPUT_VOLUME_MAX             LIV_MAX
+#define INPUT_VOLUME_RANGE           (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
+#define INPUT_VOLUME_MASK            INPUT_VOLUME_MAX
+
+#define NUMBER_SAMPLE_RATES_SUPPORTED 9
+
+static audio_stream_t output_stream = {
+        .id              = "AIC23 out",
+        .dma_dev         = OMAP_DMA_MCBSP1_TX,
+        .input_or_output = FMODE_WRITE
+};
+
+static audio_stream_t input_stream = {
+        .id              = "AIC23 in",
+        .dma_dev         = OMAP_DMA_MCBSP1_RX,
+        .input_or_output = FMODE_READ
+};
+
+static struct clk *aic23_mclk = 0;
+
+static int audio_dev_id, mixer_dev_id;
+
+static struct aic23_local_info {
+        u8  volume;
+        u16 volume_reg;
+        u8  line;
+        u8  mic;
+        u16 input_volume_reg;
+        int mod_cnt;
+} aic23_local;
+
+struct sample_rate_reg_info {
+        u32 sample_rate;
+        u8  control;            /* SR3, SR2, SR1, SR0 and BOSR */
+        u8  divider;           /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
+};
+
+/* To Store the default sample rate */
+static long audio_samplerate = AUDIO_RATE_DEFAULT;
+
+/* DAC USB-mode sampling rates (MCLK = 12 MHz) */
+static const struct sample_rate_reg_info
+reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
+        {96000, 0x0E, 0},
+        {88200, 0x1F, 0},
+        {48000, 0x00, 0},
+        {44100, 0x11, 0},
+        {32000, 0x0C, 0},
+        {24000, 0x00, 1},
+        {16000, 0x0C, 1},
+        { 8000, 0x06, 0},
+        { 4000, 0x06, 1},
+};
+
+static struct omap_mcbsp_reg_cfg initial_config = {
+        .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+        .spcr1 = RINTM(3) | RRST,
+        .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+       RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+        .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+        .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+        XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+        .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+        .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+        .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+#ifndef AIC23_MASTER
+        /* configure McBSP to be the I2S master */
+        .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
+#else
+        /* configure McBSP to be the I2S slave */
+        .pcr0  = CLKXP | CLKRP,
+#endif /* AIC23_MASTER */
+};
+
+static void omap_aic23_initialize(void *dummy);
+static void omap_aic23_shutdown(void *dummy);
+static int  omap_aic23_ioctl(struct inode *inode, struct file *file,
+                             uint cmd, ulong arg);
+static int  omap_aic23_probe(void);
+#ifdef MODULE
+static void omap_aic23_remove(void);
+#endif
+static int  omap_aic23_suspend(void);
+static int  omap_aic23_resume(void);
+static inline void aic23_configure(void);
+static int  mixer_open(struct inode *inode, struct file *file);
+static int  mixer_release(struct inode *inode, struct file *file);
+static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
+                        ulong arg);
+
+#ifdef CONFIG_PROC_FS
+static int codec_start(char *buf, char **start, off_t offset, int count,
+                       int *eof, void *data);
+static int codec_stop(char *buf, char **start, off_t offset, int count,
+                      int *eof, void *data);
+#endif
+
+
+/* File Op structure for mixer */
+static struct file_operations omap_mixer_fops = {
+        .open           = mixer_open,
+        .release        = mixer_release,
+        .ioctl          = mixer_ioctl,
+        .owner          = THIS_MODULE
+};
+
+/* To store characteristic info regarding the codec for the audio driver */
+static audio_state_t aic23_state = {
+        .output_stream  = &output_stream,
+        .input_stream   = &input_stream,
+/*     .need_tx_for_rx = 1, //Once the Full Duplex works  */
+        .need_tx_for_rx = 0,
+        .hw_init        = omap_aic23_initialize,
+        .hw_shutdown    = omap_aic23_shutdown,
+        .client_ioctl   = omap_aic23_ioctl,
+        .hw_probe       = omap_aic23_probe,
+        .hw_remove      =  __exit_p(omap_aic23_remove),
+        .hw_suspend     = omap_aic23_suspend,
+        .hw_resume      = omap_aic23_resume,
+        .sem            = __MUTEX_INITIALIZER(aic23_state.sem),
+};
+
+/* This will be defined in the audio.h */
+static struct file_operations *omap_audio_fops;
+
+extern int tlv320aic23_write_value(u8 reg, u16 value);
+
+/* TLV320AIC23 is a write only device */
+static __inline__ void audio_aic23_write(u8 address, u16 data)
+{
+        tlv320aic23_write_value(address, data);
+}
+
+static int aic23_update(int flag, int val)
+{
+        u16 volume;
+
+        /* Ignore separate left/right channel for now,
+           even the codec does support it. */
+        val &= 0xff;
+
+        if (val < 0 || val > 100) {
+                printk(KERN_ERR "Trying a bad volume value(%d)!\n",val);
+                return -EPERM;
+        }
+
+        switch (flag) {
+        case SET_VOLUME:
+                // Convert 0 -> 100 volume to 0x00 (LHV_MIN) -> 0x7f (LHV_MAX) 
+                // volume range
+                volume = ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MIN;
+                
+                // R/LHV[6:0] 1111111 (+6dB) to 0000000 (-73dB) in 1db steps,
+                // default 1111001 (0dB)
+                aic23_local.volume_reg &= ~OUTPUT_VOLUME_MASK;
+                aic23_local.volume_reg |= volume;
+                audio_aic23_write(LEFT_CHANNEL_VOLUME_ADDR, aic23_local.volume_reg);
+                audio_aic23_write(RIGHT_CHANNEL_VOLUME_ADDR, aic23_local.volume_reg);
+                break;
+
+        case SET_LINE:
+                // Convert 0 -> 100 volume to 0x0 (LIV_MIN) -> 0x1f (LIV_MAX) 
+                // volume range
+                volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
+
+                // R/LIV[4:0] 11111 (+12dB) to 00000 (-34.5dB) in 1.5dB steps,
+                // default 10111 (0dB)
+                aic23_local.input_volume_reg &= ~INPUT_VOLUME_MASK;
+                aic23_local.input_volume_reg |= volume;
+                audio_aic23_write(LEFT_LINE_VOLUME_ADDR, aic23_local.input_volume_reg);
+                audio_aic23_write(RIGHT_LINE_VOLUME_ADDR, aic23_local.input_volume_reg);
+                break;
+        }
+        return 0;
+}
+
+static int mixer_open(struct inode *inode, struct file *file)
+{
+        /* Any mixer specific initialization */
+
+        return 0;
+}
+
+static int mixer_release(struct inode *inode, struct file *file)
+{
+        /* Any mixer specific Un-initialization */
+
+        return 0;
+}
+
+static int
+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+        int val;
+        int ret = 0;
+        int nr = _IOC_NR(cmd);
+
+        /*
+         * We only accept mixer (type 'M') ioctls.
+         */
+        if (_IOC_TYPE(cmd) != 'M')
+                return -EINVAL;
+
+        DPRINTK(" 0x%08x\n", cmd);
+
+        if (cmd == SOUND_MIXER_INFO) {
+                struct mixer_info mi;
+
+                strncpy(mi.id, "AIC23", sizeof(mi.id));
+                strncpy(mi.name, "TI AIC23", sizeof(mi.name));
+                mi.modify_counter = aic23_local.mod_cnt;
+                return copy_to_user((void *)arg, &mi, sizeof(mi));
+        }
+
+        if (_IOC_DIR(cmd) & _IOC_WRITE) {
+                ret = get_user(val, (int *)arg);
+                if (ret)
+                        goto out;
+
+        
+                switch (nr) {
+                case SOUND_MIXER_VOLUME:
+                        aic23_local.volume = val;
+                        aic23_local.mod_cnt++;
+                        ret = aic23_update(SET_VOLUME, val);
+                        break;
+
+                case SOUND_MIXER_LINE:
+                        aic23_local.line = val;
+                        aic23_local.mod_cnt++;
+                        ret = aic23_update(SET_LINE, val);
+                        break;
+
+                case SOUND_MIXER_MIC:
+                        aic23_local.mic = val;
+                        aic23_local.mod_cnt++;
+                        ret = aic23_update(SET_LINE, val);
+                        break;
+
+                case SOUND_MIXER_RECSRC:
+                        break;
+
+                default:
+                        ret = -EINVAL;
+                }
+        }
+
+        if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+                ret = 0;
+
+                switch (nr) {
+                case SOUND_MIXER_VOLUME:
+                        val = aic23_local.volume;
+                        break;
+                case SOUND_MIXER_LINE:
+                        val = aic23_local.line;
+                        break;
+                case SOUND_MIXER_MIC:
+                        val = aic23_local.mic;
+                        break;
+                case SOUND_MIXER_RECSRC:
+                        val = REC_MASK;
+                        break;
+                case SOUND_MIXER_RECMASK:
+                        val = REC_MASK;
+                        break;
+                case SOUND_MIXER_DEVMASK:
+                        val = DEV_MASK;
+                        break;
+                case SOUND_MIXER_CAPS:
+                        val = 0;
+                        break;
+                case SOUND_MIXER_STEREODEVS:
+                        val = 0;
+                        break;
+                default:
+                        val = 0;
+                        ret = -EINVAL;
+                        break;
+                }
+
+                if (ret == 0)
+                        ret = put_user(val, (int *)arg);
+        }
+out:
+        return ret;
+
+}
+
+int omap_set_samplerate(long sample_rate)
+{
+        u8 count = 0;
+        u16 data = 0;
+        /* wait for any frame to complete */
+        udelay(125);
+
+        /* Search for the right sample rate */
+        while ((reg_info[count].sample_rate != sample_rate) &&
+               (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
+                count++;
+        }
+        if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
+                printk(KERN_ERR "Invalid Sample Rate %d requested\n",
+                       (int)sample_rate);
+                return -EPERM;
+        }
+
+        if (machine_is_omap_innovator()) {
+                /* set the CODEC clock input source to 12.000MHz */
+                fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~0x01, 
+                           OMAP1510_FPGA_POWER);
+        }
+
+        data = (reg_info[count].divider << CLKIN_SHIFT) | 
+                (reg_info[count].control << BOSR_SHIFT) | USB_CLK_ON;
+
+        audio_aic23_write(SAMPLE_RATE_CONTROL_ADDR, data);
+
+        audio_samplerate = sample_rate;
+
+#ifndef AIC23_MASTER
+        {
+                int clkgdv = 0;
+                /* 
+                   Set Sample Rate at McBSP
+
+                   Formula : 
+                   Codec System Clock = CODEC_CLOCK, or half if clock_divider = 1;
+                   clkgdv = ((Codec System Clock / (SampleRate * BitsPerSample * 2)) - 1);
+
+                   FWID = BitsPerSample - 1;
+                   FPER = (BitsPerSample * 2) - 1;
+                */  
+                if (reg_info[count].divider)
+                        clkgdv = CODEC_CLOCK / 2;
+                else 
+                        clkgdv = CODEC_CLOCK;
+
+                clkgdv = (clkgdv / (sample_rate * DEFAULT_BITPERSAMPLE * 2)) - 1;
+
+                initial_config.srgr1 = (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
+
+                initial_config.srgr2 =
+                        (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
+
+                omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
+        }
+#endif /* AIC23_MASTER */
+
+        return 0;
+}
+
+static void omap_aic23_initialize(void *dummy)
+{
+        DPRINTK("entry\n");
+
+        /* initialize with default sample rate */
+        audio_samplerate = AUDIO_RATE_DEFAULT;
+
+        omap_mcbsp_request(AUDIO_MCBSP);
+
+        /* if configured, then stop mcbsp */
+        omap_mcbsp_stop(AUDIO_MCBSP);
+
+        omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
+        omap_mcbsp_start(AUDIO_MCBSP);
+        aic23_configure();
+
+        DPRINTK("exit\n");
+}
+
+static void omap_aic23_shutdown(void *dummy)
+{
+        /*
+          Turn off codec after it is done.
+          Can't do it immediately, since it may still have
+          buffered data.
+
+          Wait 20ms (arbitrary value) and then turn it off.
+        */
+
+        set_current_state(TASK_INTERRUPTIBLE);
+        schedule_timeout(2);
+
+        omap_mcbsp_stop(AUDIO_MCBSP);
+        omap_mcbsp_free(AUDIO_MCBSP);
+
+        audio_aic23_write(RESET_CONTROL_ADDR, 0);
+        audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0xff);
+}
+
+static inline void aic23_configure()
+{
+        /* Reset codec */
+        audio_aic23_write(RESET_CONTROL_ADDR, 0);
+
+        /* Initialize the AIC23 internal state */
+
+        /* Left/Right line input volume control */
+        aic23_local.line = DEFAULT_INPUT_VOLUME;
+        aic23_local.mic = DEFAULT_INPUT_VOLUME;
+        aic23_update(SET_LINE, DEFAULT_INPUT_VOLUME);
+
+        /* Left/Right headphone channel volume control */
+        /* Zero-cross detect on */
+        aic23_local.volume_reg = LZC_ON;
+        aic23_update(SET_VOLUME, aic23_local.volume);
+
+        /* Analog audio path control, DAC selected, delete INSEL_MIC for line in */
+        audio_aic23_write(ANALOG_AUDIO_CONTROL_ADDR, DAC_SELECTED | INSEL_MIC);
+
+        /* Digital audio path control, de-emphasis control 44.1kHz */
+        audio_aic23_write(DIGITAL_AUDIO_CONTROL_ADDR, DEEMP_44K);
+
+        /* Power control, everything is on */
+        audio_aic23_write(POWER_DOWN_CONTROL_ADDR, 0);
+
+        /* Digital audio interface, master/slave mode, I2S, 16 bit */
+#ifdef AIC23_MASTER
+        audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, MS_MASTER | IWL_16 | FOR_DSP);
+#else
+        audio_aic23_write(DIGITAL_AUDIO_FORMAT_ADDR, IWL_16 | FOR_DSP);
+#endif /* AIC23_MASTER */
+
+        /* Enable digital interface */
+        audio_aic23_write(DIGITAL_INTERFACE_ACT_ADDR, ACT_ON);
+
+        /* clock configuration */
+        omap_set_samplerate(audio_samplerate);
+}
+
+static int
+omap_aic23_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+        long val;
+        int ret = 0;
+
+        DPRINTK(" 0x%08x\n", cmd);
+
+        /*
+         * These are platform dependent ioctls which are not handled by the
+         * generic omap-audio module.
+         */
+        switch (cmd) {
+        case SNDCTL_DSP_STEREO:
+                ret = get_user(val, (int *)arg);
+                if (ret)
+                        return ret;
+                /* the AIC23 is stereo only */
+                ret = (val == 0) ? -EINVAL : 1;
+                return put_user(ret, (int *)arg);
+
+        case SNDCTL_DSP_CHANNELS:
+        case SOUND_PCM_READ_CHANNELS:
+                /* the AIC23 is stereo only */
+                return put_user(2, (long *)arg);
+
+        case SNDCTL_DSP_SPEED:
+                ret = get_user(val, (long *)arg);
+                if (ret)
+                        break;
+                ret = omap_set_samplerate(val);
+                if (ret)
+                        break;
+                /* fall through */
+
+        case SOUND_PCM_READ_RATE:
+                return put_user(audio_samplerate, (long *)arg);
+
+        case SOUND_PCM_READ_BITS:
+        case SNDCTL_DSP_SETFMT:
+        case SNDCTL_DSP_GETFMTS:
+                /* we can do 16-bit only */
+                return put_user(AFMT_S16_LE, (long *)arg);
+
+        default:
+                /* Maybe this is meant for the mixer (As per OSS Docs) */
+                return mixer_ioctl(inode, file, cmd, arg);
+        }
+
+        return ret;
+}
+
+static int omap_aic23_probe(void)
+{
+        /* Get the fops from audio oss driver */
+        if (!(omap_audio_fops = audio_get_fops())) {
+                printk(KERN_ERR "Unable to get the file operations for AIC23 OSS driver\n");
+                audio_unregister_codec(&aic23_state);
+                return -EPERM;
+        }
+
+        aic23_local.volume = DEFAULT_OUTPUT_VOLUME;
+
+        /* register devices */
+        audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
+        mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
+
+#ifdef CONFIG_PROC_FS
+        create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
+                               NULL /* parent dir */ ,
+                               codec_start, NULL /* client data */ );
+
+        create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
+                               NULL /* parent dir */ ,
+                               codec_stop, NULL /* client data */ );
+#endif
+
+        /* Announcement Time */
+        printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
+               " audio support initialized\n");
+        return 0;
+}
+
+#ifdef MODULE
+static void __exit omap_aic23_remove(void)
+{
+        /* Un-Register the codec with the audio driver */
+        unregister_sound_dsp(audio_dev_id);
+        unregister_sound_mixer(mixer_dev_id);
+
+#ifdef CONFIG_PROC_FS
+        remove_proc_entry(PROC_START_FILE, NULL);
+        remove_proc_entry(PROC_STOP_FILE, NULL);
+#endif
+}
+#endif /* MODULE */
+
+static int omap_aic23_suspend(void)
+{
+        /* Empty for the moment */
+        return 0;
+}
+
+static int omap_aic23_resume(void)
+{
+        /* Empty for the moment */
+        return 0;
+}
+
+static int __init audio_aic23_init(void)
+{
+
+        int err = 0;
+
+       if (machine_is_omap_h2() || machine_is_omap_h3())
+               return -ENODEV;
+
+        if (machine_is_omap_osk()) {
+                /* Set MCLK to be clock input for AIC23 */
+                aic23_mclk = clk_get(0, "mclk");
+            
+                if(clk_get_rate( aic23_mclk) != CODEC_CLOCK){
+                        /* MCLK ist not at CODEC_CLOCK */
+                        if( clk_get_usecount(aic23_mclk) > 0 ){
+                                /* MCLK is already in use */
+                                printk(KERN_WARNING "MCLK in use at %d Hz. We change it to %d Hz\n",
+                                       (uint)clk_get_rate( aic23_mclk), CODEC_CLOCK);
+                        }
+                        if( clk_set_rate( aic23_mclk, CODEC_CLOCK ) ){
+                                printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
+                                return -ECANCELED;
+                       }
+               }
+
+                clk_use( aic23_mclk );
+
+                DPRINTK("MCLK = %d [%d], usecount = %d\n",(uint)clk_get_rate( aic23_mclk ), 
+                        CODEC_CLOCK, clk_get_usecount( aic23_mclk));
+        }
+
+        if (machine_is_omap_innovator()) {
+                u8 fpga;
+                /*
+                  Turn on chip select for CODEC (shared with touchscreen).  
+                  Don't turn it back off, in case touch screen needs it.
+                */                           
+                fpga = fpga_read(OMAP1510_FPGA_TOUCHSCREEN);
+                fpga |= 0x4;
+                fpga_write(fpga, OMAP1510_FPGA_TOUCHSCREEN);
+        }
+
+        /* register the codec with the audio driver */
+        if ((err = audio_register_codec(&aic23_state))) {
+                printk(KERN_ERR
+                       "Failed to register AIC23 driver with Audio OSS Driver\n");
+        }
+
+        return err;
+}
+
+static void __exit audio_aic23_exit(void)
+{
+        (void)audio_unregister_codec(&aic23_state);
+        return;
+}
+
+#ifdef CONFIG_PROC_FS
+static int codec_start(char *buf, char **start, off_t offset, int count,
+                       int *eof, void *data)
+{
+        void *foo = NULL;
+
+        omap_aic23_initialize(foo);
+
+        printk("AIC23 codec initialization done.\n");
+        return 0;
+}
+static int codec_stop(char *buf, char **start, off_t offset, int count,
+                      int *eof, void *data)
+{
+        void *foo = NULL;
+
+        omap_aic23_shutdown(foo);
+
+        printk("AIC23 codec shutdown.\n");
+        return 0;
+}
+#endif /* CONFIG_PROC_FS */
+
+module_init(audio_aic23_init);
+module_exit(audio_aic23_exit);
+
+MODULE_AUTHOR("Dirk Behme <dirk.behme@de.bosch.com>");
+MODULE_DESCRIPTION("Glue audio driver for the TI AIC23 codec.");
+MODULE_LICENSE("GPL");
diff --git a/sound/oss/omap-audio-dma-intfc.c b/sound/oss/omap-audio-dma-intfc.c
new file mode 100644 (file)
index 0000000..9f34517
--- /dev/null
@@ -0,0 +1,961 @@
+/*
+ * linux/sound/oss/omap-audio-dma-intfc.c
+ *
+ * Common audio DMA handling for the OMAP processors
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004-06-07  Sriram Kannan   - Created new file from omap_audio_dma_intfc.c. This file
+ *                               will contain only the DMA interface and buffer handling of OMAP
+ *                               audio driver.
+ *
+ * 2004-06-22  Sriram Kannan   - removed legacy code (auto-init). Self-linking of DMA logical channel.
+ *
+ * 2004-08-12   Nishanth Menon  - Modified to integrate Audio requirements on 1610,1710 platforms
+ *
+ * 2004-11-01   Nishanth Menon  - 16xx platform code base modified to support multi channel chaining.
+ *
+ * 2004-12-15   Nishanth Menon  - Improved 16xx platform channel logic introduced - tasklets, queue handling updated
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/sysrq.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+
+#include <asm/arch/dma.h>
+#include "omap-audio-dma-intfc.h"
+
+#include <asm/arch/mcbsp.h>
+
+#include "omap-audio.h"
+
+#undef DEBUG
+//#define DEBUG
+#ifdef DEBUG
+#define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
+#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
+#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
+#else
+
+#define DPRINTK( x... )
+#define FN_IN
+#define FN_OUT(x)
+#endif
+
+#define ERR(ARGS...) printk(KERN_ERR "{%s}-ERROR: ", __FUNCTION__);printk(ARGS);
+
+#define AUDIO_NAME             "omap-audio"
+#define AUDIO_NBFRAGS_DEFAULT  8
+#define AUDIO_FRAGSIZE_DEFAULT 8192
+
+#define AUDIO_ACTIVE(state)    ((state)->rd_ref || (state)->wr_ref)
+
+#define SPIN_ADDR              (dma_addr_t)0
+#define SPIN_SIZE              2048
+
+/* Channel Queue Handling macros
+ * tail always points to the current free entry
+ * Head always points to the current entry being used
+ * end is either head or tail
+ */
+
+#define AUDIO_QUEUE_INIT(s) s->dma_q_head = s->dma_q_tail = s->dma_q_count = 0;
+#define AUDIO_QUEUE_FULL(s) (nr_linked_channels == s->dma_q_count)
+#define AUDIO_QUEUE_LAST(s) (1 == s->dma_q_count)
+#define AUDIO_QUEUE_EMPTY(s) (0 == s->dma_q_count)
+#define __AUDIO_INCREMENT_QUEUE(end) ((end)=((end)+1) % nr_linked_channels)
+#define AUDIO_INCREMENT_HEAD(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_head); s->dma_q_count--;
+#define AUDIO_INCREMENT_TAIL(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_tail); s->dma_q_count++;
+
+/* DMA buffer fragmentation sizes */
+#define MAX_DMA_SIZE            0x1000000
+#define CUT_DMA_SIZE            0x1000
+/* TODO: To be moved to more appropriate location */
+#define DCSR_ERROR           0x3
+#define DCSR_SYNC_SET        (1 << 6)
+
+#define DCCR_FS              (1 << 5)
+#define DCCR_PRIO            (1 << 6)
+#define DCCR_EN              (1 << 7)
+#define DCCR_AI              (1 << 8)
+#define DCCR_REPEAT          (1 << 9)
+/* if 0 the channel works in 3.1 compatible mode*/
+#define DCCR_N31COMP         (1 << 10)
+#define DCCR_EP              (1 << 11)
+#define DCCR_SRC_AMODE_BIT   12
+#define DCCR_SRC_AMODE_MASK  (0x3<<12)
+#define DCCR_DST_AMODE_BIT   14
+#define DCCR_DST_AMODE_MASK  (0x3<<14)
+#define AMODE_CONST          0x0
+#define AMODE_POST_INC       0x1
+#define AMODE_SINGLE_INDEX   0x2
+#define AMODE_DOUBLE_INDEX   0x3
+
+/**************************** DATA STRUCTURES *****************************************/
+
+static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED;
+
+struct audio_isr_work_item {
+       int current_lch;
+       u16 ch_status;
+       audio_stream_t *s;
+};
+
+static char work_item_running = 0;
+static char nr_linked_channels = 1;
+static struct audio_isr_work_item work1, work2;
+
+
+/*********************************** MODULE SPECIFIC FUNCTIONS PROTOTYPES *************/
+
+static void audio_dsr_handler(unsigned long);
+static DECLARE_TASKLET(audio_isr_work1, audio_dsr_handler,
+               (unsigned long)&work1);
+static DECLARE_TASKLET(audio_isr_work2, audio_dsr_handler,
+               (unsigned long)&work2);
+
+static void sound_dma_irq_handler(int lch, u16 ch_status, void *data);
+static void audio_dma_callback(int lch, u16 ch_status, void *data);
+static int omap_start_sound_dma(audio_stream_t * s, dma_addr_t dma_ptr,
+                               u_int size);
+static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
+                                    u_int dma_size);
+static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
+                                       u_int dma_size);
+static int audio_start_dma_chain(audio_stream_t * s);
+
+/*********************************** GLOBAL FUNCTIONS DEFINTIONS ***********************/
+
+/***************************************************************************************
+ *
+ * Buffer creation/destruction
+ *
+ **************************************************************************************/
+int audio_setup_buf(audio_stream_t * s)
+{
+       int frag;
+       int dmasize = 0;
+       char *dmabuf = NULL;
+       dma_addr_t dmaphys = 0;
+       FN_IN;
+       if (s->buffers) {
+               FN_OUT(1);
+               return -EBUSY;
+       }
+       s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
+       if (!s->buffers)
+               goto err;
+       memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
+       for (frag = 0; frag < s->nbfrags; frag++) {
+               audio_buf_t *b = &s->buffers[frag];
+               /*
+                * Let's allocate non-cached memory for DMA buffers.
+                * We try to allocate all memory at once.
+                * If this fails (a common reason is memory fragmentation),
+                * then we allocate more smaller buffers.
+                */
+               if (!dmasize) {
+                       dmasize = (s->nbfrags - frag) * s->fragsize;
+                       do {
+                               dmabuf =
+                                   dma_alloc_coherent(NULL, dmasize, &dmaphys,
+                                                      0);
+                               if (!dmabuf)
+                                       dmasize -= s->fragsize;
+                       }
+                       while (!dmabuf && dmasize);
+                       if (!dmabuf)
+                               goto err;
+                       b->master = dmasize;
+                       memzero(dmabuf, dmasize);
+               }
+               b->data = dmabuf;
+               b->dma_addr = dmaphys;
+               dmabuf += s->fragsize;
+               dmaphys += s->fragsize;
+               dmasize -= s->fragsize;
+       }
+       s->usr_head = s->dma_head = s->dma_tail = 0;
+       AUDIO_QUEUE_INIT(s);
+       s->started = 0;
+       s->bytecount = 0;
+       s->fragcount = 0;
+       init_completion(&s->wfc);
+       s->wfc.done = s->nbfrags;
+       FN_OUT(0);
+       return 0;
+      err:
+       audio_discard_buf(s);
+       FN_OUT(1);
+       return -ENOMEM;
+}
+
+void audio_discard_buf(audio_stream_t * s)
+{
+       FN_IN;
+       /* ensure DMA isn't using those buffers */
+       audio_reset(s);
+       if (s->buffers) {
+               int frag;
+               for (frag = 0; frag < s->nbfrags; frag++) {
+                       if (!s->buffers[frag].master)
+                               continue;
+                       dma_free_coherent(NULL,
+                                         s->buffers[frag].master,
+                                         s->buffers[frag].data,
+                                         s->buffers[frag].dma_addr);
+               }
+               kfree(s->buffers);
+               s->buffers = NULL;
+       }
+       FN_OUT(0);
+}
+
+/***************************************************************************************
+ *
+ * DMA channel requests
+ *
+ **************************************************************************************/
+static void omap_sound_dma_link_lch(void *data)
+{
+       audio_stream_t *s = (audio_stream_t *) data;
+       int *chan = s->lch;
+       int i;
+
+       FN_IN;
+       if (s->linked) {
+               FN_OUT(1);
+               return;
+       }
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               int nex_chan =
+                   ((nr_linked_channels - 1 ==
+                     i) ? chan[0] : chan[i + 1]);
+               omap_dma_link_lch(cur_chan, nex_chan);
+       }
+       s->linked = 1;
+       FN_OUT(0);
+}
+
+int
+omap_request_sound_dma(int device_id, const char *device_name, void *data,
+                      int **channels)
+{
+       int i, err = 0;
+       int *chan = NULL;
+       FN_IN;
+       if (unlikely((NULL == channels) || (NULL == device_name))) {
+               BUG();
+               return -EPERM;
+       }
+       /* Try allocate memory for the num channels */
+       *channels =
+           (int *)kmalloc(sizeof(int) * nr_linked_channels,
+                          GFP_KERNEL);
+       chan = *channels;
+       if (NULL == chan) {
+               ERR("No Memory for channel allocs!\n");
+               FN_OUT(-ENOMEM);
+               return -ENOMEM;
+       }
+       spin_lock(&dma_list_lock);
+       for (i = 0; i < nr_linked_channels; i++) {
+               err =
+                   omap_request_dma(device_id, device_name,
+                                    sound_dma_irq_handler, data, &chan[i]);
+               /* Handle Failure condition here */
+               if (err < 0) {
+                       int j;
+                       for (j = 0; j < i; j++) {
+                               omap_free_dma(chan[j]);
+                       }
+                       spin_unlock(&dma_list_lock);
+                       kfree(chan);
+                       *channels = NULL;
+                       ERR("Error in requesting channel %d=0x%x\n", i, err);
+                       FN_OUT(err);
+                       return err;
+               }
+       }
+
+       /* Chain the channels together */
+       if (!cpu_is_omap1510())
+               omap_sound_dma_link_lch(data);
+
+       spin_unlock(&dma_list_lock);
+       FN_OUT(0);
+       return 0;
+}
+
+/***************************************************************************************
+ *
+ * DMA channel requests Freeing
+ *
+ **************************************************************************************/
+static void omap_sound_dma_unlink_lch(void *data)
+{
+       audio_stream_t *s = (audio_stream_t *) data;
+       int *chan = s->lch;
+       int i;
+
+       FN_IN;
+       if (!s->linked) {
+               FN_OUT(1);
+               return;
+       }
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               int nex_chan =
+                   ((nr_linked_channels - 1 ==
+                     i) ? chan[0] : chan[i + 1]);
+               omap_dma_unlink_lch(cur_chan, nex_chan);
+       }
+       s->linked = 0;
+       FN_OUT(0);
+}
+
+int omap_free_sound_dma(void *data, int **channels)
+{
+       int i;
+       int *chan = NULL;
+       FN_IN;
+       if (unlikely(NULL == channels)) {
+               BUG();
+               return -EPERM;
+       }
+       if (unlikely(NULL == *channels)) {
+               BUG();
+               return -EPERM;
+       }
+       chan = (*channels);
+
+       if (!cpu_is_omap1510())
+               omap_sound_dma_unlink_lch(data);
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               omap_stop_dma(cur_chan);
+               omap_free_dma(cur_chan);
+       }
+       kfree(*channels);
+       *channels = NULL;
+       FN_OUT(0);
+       return 0;
+}
+
+/***************************************************************************************
+ *
+ * Process DMA requests - This will end up starting the transfer. Proper fragments of
+ * Transfers will be initiated.
+ *
+ **************************************************************************************/
+int audio_process_dma(audio_stream_t * s)
+{
+       int ret = 0;
+       unsigned long flags;
+       FN_IN;
+
+       /* Dont let the ISR over ride touching the in_use flag */
+       local_irq_save(flags);
+       if (1 == s->in_use) {
+               local_irq_restore(flags);
+               ERR("Called again while In Use\n");
+               return 0;
+       }
+       s->in_use = 1;
+       local_irq_restore(flags);
+
+       if (s->stopped)
+               goto spin;
+
+       if (s->dma_spinref > 0 && s->pending_frags) {
+               s->dma_spinref = 0;
+               DMA_CLEAR(s);
+       }
+       while (s->pending_frags) {
+               audio_buf_t *b = &s->buffers[s->dma_head];
+               u_int dma_size = s->fragsize - b->offset;
+               if (dma_size > MAX_DMA_SIZE)
+                       dma_size = CUT_DMA_SIZE;
+               ret =
+                   omap_start_sound_dma(s, b->dma_addr + b->offset, dma_size);
+               if (ret) {
+                       goto process_out;
+               }
+               b->dma_ref++;
+               b->offset += dma_size;
+               if (b->offset >= s->fragsize) {
+                       s->pending_frags--;
+                       if (++s->dma_head >= s->nbfrags)
+                               s->dma_head = 0;
+               }
+       }
+      spin:
+       if (s->spin_idle) {
+               int spincnt = 0;
+               ERR("we are spinning\n");
+               while (omap_start_sound_dma(s, SPIN_ADDR, SPIN_SIZE) == 0)
+                       spincnt++;
+               /*
+                * Note: if there is still a data buffer being
+                * processed then the ref count is negative.  This
+                * allows for the DMA termination to be accounted in
+                * the proper order.  Of course dma_spinref can't be
+                * greater than 0 if dma_ref is not 0 since we kill
+                * the spinning above as soon as there is real data to process.
+                */
+               if (s->buffers && s->buffers[s->dma_tail].dma_ref)
+                       spincnt = -spincnt;
+               s->dma_spinref += spincnt;
+       }
+
+      process_out:
+       s->in_use = 0;
+
+       FN_OUT(ret);
+       return ret;
+}
+
+/***************************************************************************************
+ *
+ * Prime Rx - Since the recieve buffer has no time limit as to when it would arrive,
+ *            we need to prime it
+ *            
+ **************************************************************************************/
+void audio_prime_rx(audio_state_t * state)
+{
+       audio_stream_t *is = state->input_stream;
+
+       FN_IN;
+       if (state->need_tx_for_rx) {
+               /*
+                * With some codecs like the Philips UDA1341 we must ensure
+                * there is an output stream at any time while recording since
+                * this is how the UDA1341 gets its clock from the SA1100.
+                * So while there is no playback data to send, the output DMA
+                * will spin with all zeroes.  We use the cache flush special
+                * area for that.
+                */
+               state->output_stream->spin_idle = 1;
+               audio_process_dma(state->output_stream);
+       }
+       is->pending_frags = is->nbfrags;
+       init_completion(&is->wfc);
+       is->wfc.done = 0;
+
+       is->active = 1;
+       audio_process_dma(is);
+
+       FN_OUT(0);
+       return;
+}
+
+/***************************************************************************************
+ *
+ * set the fragment size
+ *
+ **************************************************************************************/
+int audio_set_fragments(audio_stream_t * s, int val)
+{
+       FN_IN;
+       if (s->active)
+               return -EBUSY;
+       if (s->buffers)
+               audio_discard_buf(s);
+       s->nbfrags = (val >> 16) & 0x7FFF;
+       val &= 0xFFFF;
+       if (val < 4)
+               val = 4;
+       if (val > 15)
+               val = 15;
+       s->fragsize = 1 << val;
+       if (s->nbfrags < 2)
+               s->nbfrags = 2;
+       if (s->nbfrags * s->fragsize > 128 * 1024)
+               s->nbfrags = 128 * 1024 / s->fragsize;
+       FN_OUT(0);
+       if (audio_setup_buf(s))
+               return -ENOMEM;
+       return val | (s->nbfrags << 16);
+
+}
+
+/***************************************************************************************
+ *
+ * Sync up the buffers before we shutdown, else under-run errors will happen
+ *
+ **************************************************************************************/
+int audio_sync(struct file *file)
+{
+       audio_state_t *state = file->private_data;
+       audio_stream_t *s = state->output_stream;
+       audio_buf_t *b;
+       u_int shiftval = 0;
+       unsigned long flags;
+
+       DECLARE_WAITQUEUE(wait, current);
+
+       FN_IN;
+
+       if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped) {
+               FN_OUT(1);
+               return 0;
+       }
+
+       /*
+        * Send current buffer if it contains data.  Be sure to send
+        * a full sample count.
+        */
+       b = &s->buffers[s->usr_head];
+       if (b->offset &= ~3) {
+               /* Wait for a buffer to become free */
+               if (wait_for_completion_interruptible(&s->wfc))
+                       return 0;
+               /*
+                * HACK ALERT !
+                * To avoid increased complexity in the rest of the code
+                * where full fragment sizes are assumed, we cheat a little
+                * with the start pointer here and don't forget to restore
+                * it later.
+                */
+               
+               /* As this is a last frag we need only one dma channel
+                * to complete. So it's need to unlink dma channels
+                * to avoid empty dma work.
+                */
+               if (!cpu_is_omap1510() && AUDIO_QUEUE_EMPTY(s))
+                       omap_sound_dma_unlink_lch(s);
+
+               shiftval = s->fragsize - b->offset;
+               b->offset = shiftval;
+               b->dma_addr -= shiftval;
+               b->data -= shiftval;
+               local_irq_save(flags);
+               s->bytecount -= shiftval;
+               if (++s->usr_head >= s->nbfrags)
+                       s->usr_head = 0;
+
+               s->pending_frags++;
+               audio_process_dma(s);
+               local_irq_restore(flags);
+       }
+
+       /* Let's wait for all buffers to complete */
+       set_current_state(TASK_INTERRUPTIBLE);
+       add_wait_queue(&s->wq, &wait);
+       while ((s->pending_frags || (s->wfc.done < s->nbfrags))
+              && !signal_pending(current)) {
+               schedule();
+               set_current_state(TASK_INTERRUPTIBLE);
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&s->wq, &wait);
+
+       /* undo the pointer hack above */
+       if (shiftval) {
+               local_irq_save(flags);
+               b->dma_addr += shiftval;
+               b->data += shiftval;
+               /* ensure sane DMA code behavior if not yet processed */
+               if (b->offset != 0)
+                       b->offset = s->fragsize;
+               local_irq_restore(flags);
+       }
+
+       FN_OUT(0);
+       return 0;
+}
+
+/***************************************************************************************
+ *
+ * Stop all the DMA channels of the stream
+ *
+ **************************************************************************************/
+void audio_stop_dma(audio_stream_t * s)
+{
+       int *chan = s->lch;
+       int i;
+       FN_IN;
+       if (unlikely(NULL == chan)) {
+               BUG();
+               return;
+       }
+       for (i = 0; i < nr_linked_channels; i++) {
+               int cur_chan = chan[i];
+               omap_stop_dma(cur_chan);
+       }
+       s->started = 0;
+       FN_OUT(0);
+       return;
+}
+
+/***************************************************************************************
+ *
+ * Get the dma posn
+ *
+ **************************************************************************************/
+u_int audio_get_dma_pos(audio_stream_t * s)
+{
+       audio_buf_t *b = &s->buffers[s->dma_tail];
+       u_int offset;
+
+       FN_IN;
+       if (b->dma_ref) {
+               offset = omap_get_dma_src_pos(s->lch[s->dma_q_head]) - b->dma_addr;
+               if (offset >= s->fragsize)
+                       offset = s->fragsize - 4;
+       } else if (s->pending_frags) {
+               offset = b->offset;
+       } else {
+               offset = 0;
+       }
+       FN_OUT(offset);
+       return offset;
+}
+
+/***************************************************************************************
+ *
+ * Reset the audio buffers
+ *
+ **************************************************************************************/
+void audio_reset(audio_stream_t * s)
+{
+       FN_IN;
+       if (s->buffers) {
+               audio_stop_dma(s);
+               s->buffers[s->dma_head].offset = 0;
+               s->buffers[s->usr_head].offset = 0;
+               s->usr_head = s->dma_head;
+               s->pending_frags = 0;
+               init_completion(&s->wfc);
+               s->wfc.done = s->nbfrags;
+       }
+       s->active = 0;
+       s->stopped = 0;
+       s->started = 0;
+       FN_OUT(0);
+       return;
+}
+
+/***************************************************************************************
+ *
+ * Clear any pending transfers
+ *
+ **************************************************************************************/
+void omap_clear_sound_dma(audio_stream_t * s)
+{
+       FN_IN;
+       omap_clear_dma(s->lch[s->dma_q_head]);
+       FN_OUT(0);
+       return;
+}
+
+/*********************************** MODULE FUNCTIONS DEFINTIONS ***********************/
+
+#ifdef OMAP1610_MCBSP1_BASE
+#undef OMAP1610_MCBSP1_BASE
+#endif
+#define OMAP1610_MCBSP1_BASE    0xE1011000
+
+/***************************************************************************************
+ *
+ * DMA related functions
+ *
+ **************************************************************************************/
+static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
+                                    u_int dma_size)
+{
+       int dt = 0x1;           /* data type 16 */
+       int cen = 32;           /* Stereo */
+       int cfn = dma_size / (2 * cen);
+       FN_IN;
+       omap_set_dma_dest_params(channel, 0x05, 0x00,
+                                (OMAP1610_MCBSP1_BASE + 0x806),
+                                0, 0);
+       omap_set_dma_src_params(channel, 0x00, 0x01, dma_ptr, 0, 0);
+       omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
+       FN_OUT(0);
+       return 0;
+}
+
+static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
+                                       u_int dma_size)
+{
+       int dt = 0x1;           /* data type 16 */
+       int cen = 16;           /* mono */
+       int cfn = dma_size / (2 * cen);
+       FN_IN;
+       omap_set_dma_src_params(channel, 0x05, 0x00,
+                               (OMAP1610_MCBSP1_BASE + 0x802),
+                               0, 0);
+       omap_set_dma_dest_params(channel, 0x00, 0x01, dma_ptr, 0, 0);
+       omap_set_dma_transfer_params(channel, dt, cen, cfn, 0x00, 0, 0);
+       FN_OUT(0);
+       return 0;
+}
+
+static int audio_start_dma_chain(audio_stream_t * s)
+{
+       int channel = s->lch[s->dma_q_head];
+       FN_IN;
+       if (!s->started) {
+               omap_start_dma(channel);
+               s->started = 1;
+       }
+       /* else the dma itself will progress forward with out our help */
+       FN_OUT(0);
+       return 0;
+}
+
+/* Start DMA -
+ * Do the initial set of work to initialize all the channels as required.
+ * We shall then initate a transfer
+ */
+static int omap_start_sound_dma(audio_stream_t * s, dma_addr_t dma_ptr,
+                               u_int dma_size)
+{
+       int ret = -EPERM;
+
+       FN_IN;
+       if (unlikely(dma_size > MAX_DMA_SIZE)) {
+               ERR("DmaSoundDma: Start: overflowed %d-%d\n", dma_size,
+                   MAX_DMA_SIZE);
+               return -EOVERFLOW;
+       }
+
+       if (AUDIO_QUEUE_FULL(s)) {
+               ret = -2;
+               goto sound_out;
+       }
+       
+       if (s->input_or_output == FMODE_WRITE)
+               /*playback */
+       {
+               ret =
+                   audio_set_dma_params_play(s->lch[s->dma_q_tail], dma_ptr,
+                                             dma_size);
+       } else {
+               ret =
+                   audio_set_dma_params_capture(s->lch[s->dma_q_tail], dma_ptr,
+                                                dma_size);
+       }
+       if (ret != 0) {
+               ret = -2;       /* indicate queue full */
+               goto sound_out;
+       }
+       AUDIO_INCREMENT_TAIL(s);
+       ret = audio_start_dma_chain(s);
+       if (ret) {
+               ERR("dma start failed");
+       }
+      sound_out:
+       FN_OUT(ret);
+       return ret;
+
+}
+
+/***************************************************************************************
+ *
+ * ISR related functions
+ *
+ **************************************************************************************/
+/* The work item handler */
+static void audio_dsr_handler(unsigned long inData)
+{
+       void *data = (void *)inData;
+       struct audio_isr_work_item *work = data;
+       audio_stream_t *s = (work->s);
+       int sound_curr_lch = work->current_lch;
+       u16 ch_status = work->ch_status;
+
+       FN_IN;
+       DPRINTK("lch=%d,status=0x%x, data=%p as=%p\n", sound_curr_lch,
+               ch_status, data, s);
+       if (AUDIO_QUEUE_EMPTY(s)) {
+               ERR("Interrupt(%d)  for empty queue(h=%d, T=%d)???\n",
+                   sound_curr_lch, s->dma_q_head, s->dma_q_tail);
+               ERR("nbfrag=%d,pendfrags=%d,USR-H=%d, QH-%d QT-%d\n",
+                   s->nbfrags, s->pending_frags, s->usr_head, s->dma_head,
+                   s->dma_tail);
+               FN_OUT(-1);
+               return;
+       }
+
+       AUDIO_INCREMENT_HEAD(s);        /* Empty the queue */
+
+       /* Try to fill again */
+       audio_dma_callback(sound_curr_lch, ch_status, s);
+       FN_OUT(0);
+
+}
+
+/* Macro to trace the IRQ calls - checks for multi-channel irqs */
+//#define IRQ_TRACE
+#ifdef IRQ_TRACE
+#define MAX_UP 10
+static char xyz[MAX_UP] = { 0 };
+static int h = 0;
+#endif
+
+/* ISRs have to be short and smart.. So we transfer every heavy duty stuff to the 
+ * work item
+ */
+static void sound_dma_irq_handler(int sound_curr_lch, u16 ch_status, void *data)
+{
+       int dma_status = ch_status;
+       audio_stream_t *s = (audio_stream_t *) data;
+       FN_IN;
+#ifdef IRQ_TRACE
+       xyz[h++] = '0' + sound_curr_lch;
+       if (h == MAX_UP - 1) {
+               printk("%s-", xyz);
+               h = 0;
+       }
+#endif
+       DPRINTK("lch=%d,status=0x%x, dma_status=%d, data=%p\n", sound_curr_lch,
+               ch_status, dma_status, data);
+
+       if (dma_status & (DCSR_ERROR)) {
+               OMAP_DMA_CCR_REG(sound_curr_lch) &= ~DCCR_EN;
+               ERR("DCSR_ERROR!\n");
+               FN_OUT(-1);
+               return;
+       }
+
+       if (AUDIO_QUEUE_LAST(s))
+               audio_stop_dma(s);
+
+       /* Start the work item  - we ping pong the work items */
+       if (!work_item_running) {
+               work1.current_lch = sound_curr_lch;
+               work1.ch_status = ch_status;
+               work1.s = s;
+               /* schedule tasklet 1 */
+               tasklet_schedule(&audio_isr_work1);
+               work_item_running = 1;
+       } else {
+               work2.current_lch = sound_curr_lch;
+               work2.ch_status = ch_status;
+               work2.s = s;
+               /* schedule tasklet 2 */
+               tasklet_schedule(&audio_isr_work2);
+               work_item_running = 0;
+       }
+       FN_OUT(0);
+       return;
+}
+
+/* The call back that handles buffer stuff */
+static void audio_dma_callback(int lch, u16 ch_status, void *data)
+{
+       audio_stream_t *s = data;
+       audio_buf_t *b = &s->buffers[s->dma_tail];
+       FN_IN;
+
+       if (s->dma_spinref > 0) {
+               s->dma_spinref--;
+       } else if (!s->buffers) {
+               printk(KERN_CRIT
+                      "omap_audio: received DMA IRQ for non existent buffers!\n");
+               return;
+       } else if (b->dma_ref && --b->dma_ref == 0 && b->offset >= s->fragsize) {
+               /* This fragment is done */
+               b->offset = 0;
+               s->bytecount += s->fragsize;
+               s->fragcount++;
+               s->dma_spinref = -s->dma_spinref;
+
+               if (++s->dma_tail >= s->nbfrags)
+                       s->dma_tail = 0;
+
+               if (!s->mapped)
+                       complete(&s->wfc);
+               else
+                       s->pending_frags++;
+
+               wake_up(&s->wq);
+       }
+
+       audio_process_dma(s);
+       
+       FN_OUT(0);
+       return;
+}
+
+/*********************************************************************************
+ *
+ * audio_get_dma_callback(): return the dma interface call back function
+ *
+ *********************************************************************************/
+dma_callback_t audio_get_dma_callback(void)
+{
+       FN_IN;
+       FN_OUT(0);
+       return audio_dma_callback;
+}
+
+static int __init audio_dma_init(void)
+{
+       if (!cpu_is_omap1510())
+               nr_linked_channels = 2;
+
+       return 0;
+}
+
+static void __exit audio_dma_exit(void)
+{
+       /* Nothing */
+}
+
+module_init(audio_dma_init);
+module_exit(audio_dma_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("Common DMA handling for Audio driver on OMAP processors");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(omap_clear_sound_dma);
+EXPORT_SYMBOL(omap_request_sound_dma);
+EXPORT_SYMBOL(omap_free_sound_dma);
+
+EXPORT_SYMBOL(audio_get_dma_callback);
+EXPORT_SYMBOL(audio_setup_buf);
+EXPORT_SYMBOL(audio_process_dma);
+EXPORT_SYMBOL(audio_prime_rx);
+EXPORT_SYMBOL(audio_set_fragments);
+EXPORT_SYMBOL(audio_sync);
+EXPORT_SYMBOL(audio_stop_dma);
+EXPORT_SYMBOL(audio_get_dma_pos);
+EXPORT_SYMBOL(audio_reset);
+EXPORT_SYMBOL(audio_discard_buf);
diff --git a/sound/oss/omap-audio-dma-intfc.h b/sound/oss/omap-audio-dma-intfc.h
new file mode 100644 (file)
index 0000000..65aa528
--- /dev/null
@@ -0,0 +1,63 @@
+/*  
+ * linux/sound/oss/omap-audio-dma-intfc.h
+ *
+ * Common audio DMA handling for the OMAP processors
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004/08/12  Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms
+ */
+
+#ifndef __OMAP_AUDIO_DMA_INTFC_H
+#define __OMAP_AUDIO_DMA_INTFC_H
+
+/************************** INCLUDES *************************************/
+
+/* Requires omap-audio.h */
+#include "omap-audio.h"
+
+/************************** GLOBAL MACROS *************************************/
+
+/* Provide the Macro interfaces common across platforms */
+#define DMA_REQUEST(e,s, cb)   {e=omap_request_sound_dma(s->dma_dev, s->id, s, &s->lch);}
+#define DMA_FREE(s)            omap_free_sound_dma(s, &s->lch)
+#define DMA_CLEAR(s)           omap_clear_sound_dma(s)
+
+/************************** GLOBAL DATA STRUCTURES *********************************/
+
+typedef void (*dma_callback_t) (int lch, u16 ch_status, void *data);
+
+/************************** GLOBAL FUNCTIONS ***************************************/
+
+dma_callback_t audio_get_dma_callback(void);
+int audio_setup_buf(audio_stream_t * s);
+int audio_process_dma(audio_stream_t * s);
+void audio_prime_rx(audio_state_t * state);
+int audio_set_fragments(audio_stream_t * s, int val);
+int audio_sync(struct file *file);
+void audio_stop_dma(audio_stream_t * s);
+u_int audio_get_dma_pos(audio_stream_t * s);
+void audio_reset(audio_stream_t * s);
+void audio_discard_buf(audio_stream_t * s);
+
+/**************** ARCH SPECIFIC FUNCIONS *******************************************/
+
+void omap_clear_sound_dma(audio_stream_t * s);
+
+int omap_request_sound_dma(int device_id, const char *device_name, void *data,
+                          int **channels);
+int omap_free_sound_dma(void *data, int **channels);
+
+#endif                         /* #ifndef __OMAP_AUDIO_DMA_INTFC_H */
diff --git a/sound/oss/omap-audio-tsc2101.c b/sound/oss/omap-audio-tsc2101.c
new file mode 100644 (file)
index 0000000..320e377
--- /dev/null
@@ -0,0 +1,1222 @@
+/*
+ * linux/sound/oss/omap-audio-tsc2101.c
+ *
+ * Glue driver for TSC2101 for OMAP processors
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *  -------
+ *  2004-08-12 Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms.
+ *  2004-09-14 Sriram Kannan - Added /proc support for asynchronous starting/stopping the codec
+ *             (without affecting the normal driver flow).
+ *  2004-11-04 Nishanth Menon - Support for power management
+ *  2004-11-07 Nishanth Menon - Support for Common TSC access b/w Touchscreen and audio drivers
+ */
+
+/***************************** INCLUDES ************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/arch/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/io.h>
+#include <asm/mach-types.h>
+
+#include "omap-audio.h"
+#include "omap-audio-dma-intfc.h"
+#include <asm/arch/mcbsp.h>
+#if CONFIG_ARCH_OMAP16XX
+#include <../drivers/ssi/omap-uwire.h>
+#include <asm/arch/dsp_common.h>
+#else
+#error "Unsupported configuration"
+#endif
+
+#include <asm/hardware/tsc2101.h>
+#include <../drivers/ssi/omap-tsc2101.h>
+
+/***************************** MACROS ************************************/
+
+#define PROC_SUPPORT
+
+#ifdef PROC_SUPPORT
+#include <linux/proc_fs.h>
+#define PROC_START_FILE "driver/tsc2101-audio-start"
+#define PROC_STOP_FILE  "driver/tsc2101-audio-stop"
+#endif
+
+#define CODEC_NAME              "TSC2101"
+
+#if CONFIG_ARCH_OMAP16XX
+#define PLATFORM_NAME "OMAP16XX"
+#endif
+
+#if CONFIG_ARCH_OMAP16XX
+#define OMAP_DSP_BASE        0xE0000000
+#endif
+
+/* Define to set the tsc as the master w.r.t McBSP */
+#define TSC_MASTER
+
+/*
+ * AUDIO related MACROS
+ */
+#define DEFAULT_BITPERSAMPLE          16
+#define AUDIO_RATE_DEFAULT               44100
+#define PAGE2_AUDIO_CODEC_REGISTERS   (2)
+#define LEAVE_CS                                 0x80
+
+/* Select the McBSP For Audio */
+#if CONFIG_ARCH_OMAP16XX
+#define AUDIO_MCBSP                   OMAP_MCBSP1
+#else
+#error "UnSupported Configuration"
+#endif
+
+#define REC_MASK                                 (SOUND_MASK_LINE | SOUND_MASK_MIC)
+#define DEV_MASK                                 (REC_MASK | SOUND_MASK_VOLUME)
+
+#define SET_VOLUME                               1
+#define SET_LINE                                 2
+#define SET_MIC              3
+#define SET_RECSRC           4
+
+#define DEFAULT_VOLUME                93
+#define DEFAULT_INPUT_VOLUME     20    /* An minimal volume */
+
+/* Tsc Audio Specific */
+#define NUMBER_SAMPLE_RATES_SUPPORTED 16
+#define OUTPUT_VOLUME_MIN 0x7F
+#define OUTPUT_VOLUME_MAX 0x32
+#define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX)
+#define OUTPUT_VOLUME_MASK            OUTPUT_VOLUME_MIN
+#define DEFAULT_VOLUME_LEVEL          OUTPUT_VOLUME_MAX
+
+/* use input vol of 75 for 0dB gain */
+#define INPUT_VOLUME_MIN                     0x0
+#define INPUT_VOLUME_MAX        0x7D
+#define INPUT_VOLUME_RANGE                   (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
+#define INPUT_VOLUME_MASK                    INPUT_VOLUME_MAX
+
+/*********** Debug Macros ********/
+/* To Generate a rather shrill tone -test the entire path */
+//#define TONE_GEN
+/* To Generate a tone for each keyclick - test the tsc,spi paths*/
+//#define TEST_KEYCLICK
+/* To dump the tsc registers for debug */
+//#define TSC_DUMP_REGISTERS
+
+#ifdef DPRINTK
+#undef DPRINTK
+#endif
+#undef DEBUG
+
+//#define DEBUG
+#ifdef DEBUG
+#define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
+#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
+#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
+#else
+#define DPRINTK( x... )
+#define FN_IN
+#define FN_OUT(n)
+#endif
+
+/***************************** Data Structures **********************************/
+
+static audio_stream_t output_stream = {
+       .id              = "TSC2101 out",
+       .dma_dev         = OMAP_DMA_MCBSP1_TX,
+       .input_or_output = FMODE_WRITE
+};
+
+static audio_stream_t input_stream = {
+       .id              = "TSC2101 in",
+       .dma_dev         = OMAP_DMA_MCBSP1_RX,
+       .input_or_output = FMODE_READ
+};
+
+static int audio_dev_id, mixer_dev_id;
+
+typedef struct {
+       u8      volume;
+       u8      line;
+       u8      mic;
+       int     recsrc;
+       int     mod_cnt;
+} tsc2101_local_info;
+
+static tsc2101_local_info tsc2101_local = {
+       volume:         DEFAULT_VOLUME,
+       line:           DEFAULT_INPUT_VOLUME,
+       mic:            DEFAULT_INPUT_VOLUME,
+       recsrc:         SOUND_MASK_LINE,
+       mod_cnt:        0
+};
+
+struct sample_rate_reg_info {
+       u16 sample_rate;
+       u8  divisor;
+       u8  fs_44kHz;           /* if 0 48 khz, if 1 44.1 khz fsref */
+};
+
+/* To Store the default sample rate */
+static long audio_samplerate = AUDIO_RATE_DEFAULT;
+
+static const struct sample_rate_reg_info
+ reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
+       /* Div 1 */
+       {48000, 0, 0},
+       {44100, 0, 1},
+       /* Div 1.5 */
+       {32000, 1, 0},
+       {29400, 1, 1},
+       /* Div 2 */
+       {24000, 2, 0},
+       {22050, 2, 1},
+       /* Div 3 */
+       {16000, 3, 0},
+       {14700, 3, 1},
+       /* Div 4 */
+       {12000, 4, 0},
+       {11025, 4, 1},
+       /* Div 5 */
+       {9600, 5, 0},
+       {8820, 5, 1},
+       /* Div 5.5 */
+       {8727, 6, 0},
+       {8018, 6, 1},
+       /* Div 6 */
+       {8000, 7, 0},
+       {7350, 7, 1},
+};
+
+static struct omap_mcbsp_reg_cfg initial_config = {
+       .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+       .spcr1 = RINTM(3) | RRST,
+       .rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+                RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+       .rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+       .xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+                XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+       .xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+       .srgr1 = FWID(15),
+       .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
+
+       /* platform specific initialization */
+#if CONFIG_MACH_OMAP_H2
+       .pcr0  = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+#elif CONFIG_MACH_OMAP_H3
+
+#ifndef TSC_MASTER
+       .pcr0  = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
+#else
+       .pcr0  = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
+#endif                         /* tsc Master defs */
+
+#endif                         /* platform specific inits */
+};
+
+/***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
+
+static void omap_tsc2101_initialize(void *dummy);
+
+static void omap_tsc2101_shutdown(void *dummy);
+
+static int  omap_tsc2101_ioctl(struct inode *inode, struct file *file,
+                              uint cmd, ulong arg);
+
+static int  omap_tsc2101_probe(void);
+
+static void omap_tsc2101_remove(void);
+
+static int  omap_tsc2101_suspend(void);
+
+static int  omap_tsc2101_resume(void);
+
+static void tsc2101_configure(void);
+
+static int  mixer_open(struct inode *inode, struct file *file);
+
+static int  mixer_release(struct inode *inode, struct file *file);
+
+static int  mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
+                       ulong arg);
+
+#ifdef TEST_KEYCLICK
+void tsc2101_testkeyclick(void);
+#endif
+
+#ifdef TONE_GEN
+void toneGen(void);
+#endif
+
+#ifdef TSC_DUMP_REGISTERS
+static void tsc2101_dumpRegisters(void);
+#endif
+
+#ifdef PROC_SUPPORT
+static int codec_start(char *buf, char **start, off_t offset, int count,
+                      int *eof, void *data);
+
+static int codec_stop(char *buf, char **start, off_t offset, int count,
+                     int *eof, void *data);
+
+static void tsc2101_start(void);
+#endif
+
+/******************** DATA STRUCTURES USING FUNCTION POINTERS **************************/
+
+/* File Op structure for mixer */
+static struct file_operations omap_mixer_fops = {
+       .open           = mixer_open,
+       .release        = mixer_release,
+       .ioctl          = mixer_ioctl,
+       .owner          = THIS_MODULE
+};
+
+/* To store characteristic info regarding the codec for the audio driver */
+static audio_state_t tsc2101_state = {
+       .output_stream  = &output_stream,
+       .input_stream   = &input_stream,
+/*     .need_tx_for_rx = 1, //Once the Full Duplex works  */
+       .need_tx_for_rx = 0,
+       .hw_init        = omap_tsc2101_initialize,
+       .hw_shutdown    = omap_tsc2101_shutdown,
+       .client_ioctl   = omap_tsc2101_ioctl,
+       .hw_probe       = omap_tsc2101_probe,
+       .hw_remove      = omap_tsc2101_remove,
+       .hw_suspend     = omap_tsc2101_suspend,
+       .hw_resume      = omap_tsc2101_resume,
+       .sem            = __MUTEX_INITIALIZER(tsc2101_state.sem),
+};
+
+/* This will be defined in the Audio.h */
+static struct file_operations *omap_audio_fops;
+
+/***************************** MODULES SPECIFIC FUNCTIONs *******************************/
+
+/*********************************************************************************
+ *
+ * Simplified write for tsc Audio
+ *
+ *********************************************************************************/
+static __inline__ void audio_tsc2101_write(u8 address, u16 data)
+{
+       omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
+}
+
+/*********************************************************************************
+ *
+ * Simplified read for tsc  Audio
+ *
+ *********************************************************************************/
+static __inline__ u16 audio_tsc2101_read(u8 address)
+{
+       return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
+}
+
+/*********************************************************************************
+ *
+ * tsc2101_update()
+ * Volume Adj etc
+ *
+ ********************************************************************************/
+static int tsc2101_update(int flag, int val)
+{
+       u16 volume;
+       u16 data;
+
+       FN_IN;
+       switch (flag) {
+       case SET_VOLUME:
+               if (val < 0 || val > 100) {
+                       printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
+                       return -EPERM;
+               }
+               /* Convert 0 -> 100 volume to 0x7F(min) -> y(max) volume range */
+               volume =
+                   ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MAX;
+               /* invert the value for getting the proper range 0 min and 100 max */
+               volume = OUTPUT_VOLUME_MIN - volume;
+               data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
+               data &=
+                   ~(DGC_DALVL(OUTPUT_VOLUME_MIN) |
+                     DGC_DARVL(OUTPUT_VOLUME_MIN));
+               data |= DGC_DALVL(volume) | DGC_DARVL(volume);
+               audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, data);
+               data = audio_tsc2101_read(TSC2101_DAC_GAIN_CTRL);
+
+               break;
+
+       case SET_LINE:
+               if (val < 0 || val > 100) {
+                       printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
+                       return -EPERM;
+               }
+               /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
+               /* NOTE: 0 is minimum volume and not mute */
+               volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
+               /* Handset Input not muted, AGC for Handset In off */
+               audio_tsc2101_write(TSC2101_HEADSET_GAIN_CTRL,
+       HGC_ADPGA_HED(volume));
+               break;
+
+       case SET_MIC:
+               if (val < 0 || val > 100) {
+                       printk(KERN_ERR "Trying a bad volume value(%d)!\n", val);
+                       return -EPERM;
+               }
+               /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
+               /* NOTE: 0 is minimum volume and not mute */
+               volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
+               /* Handset Input not muted, AGC for Handset In off */
+               audio_tsc2101_write(TSC2101_HANDSET_GAIN_CTRL,
+       HNGC_ADPGA_HND(volume));
+               break;
+
+       case SET_RECSRC:
+               /*
+                * If more than one recording device selected,
+                * disable the device that is currently in use.
+                */
+               if (hweight32(val) > 1)
+                       val &= ~tsc2101_local.recsrc;
+
+               data = audio_tsc2101_read(TSC2101_MIXER_PGA_CTRL);
+               data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */
+
+               if (val == SOUND_MASK_MIC) {
+                       data |=  MPC_MICSEL(1);
+                       audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
+               }
+               else if (val == SOUND_MASK_LINE) {
+                       data |=  MPC_MICSEL(0);
+                       audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL, data);
+               }
+               else {
+                       printk(KERN_WARNING "omap1610-tsc2101: Wrong RECSRC"
+        " value specified\n");
+                       return -EINVAL;
+               }
+               tsc2101_local.recsrc = val;
+               break;
+       default:
+               printk(KERN_WARNING "omap1610-tsc2101: Wrong tsc2101_update "
+       "flag specified\n");
+               break;
+       }
+
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * mixer_open()
+ *
+ ********************************************************************************/
+static int mixer_open(struct inode *inode, struct file *file)
+{
+       /* Any mixer specific initialization */
+
+       /* Initalize the tsc2101 */
+       omap_tsc2101_enable();
+
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * mixer_release()
+ *
+ ********************************************************************************/
+static int mixer_release(struct inode *inode, struct file *file)
+{
+       /* Any mixer specific Un-initialization */
+       omap_tsc2101_disable();
+
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * mixer_ioctl()
+ *
+ ********************************************************************************/
+static int
+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+       int val;
+       int gain;
+       int ret = 0;
+       int nr = _IOC_NR(cmd);
+
+       /*
+        * We only accept mixer (type 'M') ioctls.
+        */
+       FN_IN;
+       if (_IOC_TYPE(cmd) != 'M')
+               return -EINVAL;
+
+       DPRINTK(" 0x%08x\n", cmd);
+
+       if (cmd == SOUND_MIXER_INFO) {
+               struct mixer_info mi;
+
+               strncpy(mi.id, "TSC2101", sizeof(mi.id));
+               strncpy(mi.name, "TI TSC2101", sizeof(mi.name));
+               mi.modify_counter = tsc2101_local.mod_cnt;
+               FN_OUT(1);
+               return copy_to_user((void __user *)arg, &mi, sizeof(mi));
+       }
+
+       if (_IOC_DIR(cmd) & _IOC_WRITE) {
+               ret = get_user(val, (int __user *)arg);
+               if (ret)
+                       goto out;
+
+               /* Ignore separate left/right channel for now,
+                * even the codec does support it.
+                */
+               gain = val & 255;
+
+               switch (nr) {
+               case SOUND_MIXER_VOLUME:
+                       tsc2101_local.volume = val;
+                       tsc2101_local.mod_cnt++;
+                       ret = tsc2101_update(SET_VOLUME, gain);
+                       break;
+
+               case SOUND_MIXER_LINE:
+                       tsc2101_local.line = val;
+                       tsc2101_local.mod_cnt++;
+                       ret = tsc2101_update(SET_LINE, gain);
+                       break;
+
+               case SOUND_MIXER_MIC:
+                       tsc2101_local.mic = val;
+                       tsc2101_local.mod_cnt++;
+                       ret = tsc2101_update(SET_MIC, gain);
+                       break;
+
+               case SOUND_MIXER_RECSRC:
+                       if ((val & SOUND_MASK_LINE) ||
+                           (val & SOUND_MASK_MIC)) {
+                               if (tsc2101_local.recsrc != val) {
+                                       tsc2101_local.mod_cnt++;
+                                       tsc2101_update(SET_RECSRC, val);
+                               }
+                       }
+                       else {
+                               ret = -EINVAL;
+                       }
+                       break;
+
+               default:
+                       ret = -EINVAL;
+               }
+       }
+
+       if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+               ret = 0;
+
+               switch (nr) {
+               case SOUND_MIXER_VOLUME:
+                       val = tsc2101_local.volume;
+                       val = (tsc2101_local.volume << 8) |
+         tsc2101_local.volume;
+                       break;
+               case SOUND_MIXER_LINE:
+                       val = (tsc2101_local.line << 8) |
+         tsc2101_local.line;
+                       break;
+               case SOUND_MIXER_MIC:
+                       val = (tsc2101_local.mic << 8) |
+         tsc2101_local.mic;
+                       break;
+               case SOUND_MIXER_RECSRC:
+                       val = tsc2101_local.recsrc;
+                       break;
+               case SOUND_MIXER_RECMASK:
+                       val = REC_MASK;
+                       break;
+               case SOUND_MIXER_DEVMASK:
+                       val = DEV_MASK;
+                       break;
+               case SOUND_MIXER_CAPS:
+                       val = 0;
+                       break;
+               case SOUND_MIXER_STEREODEVS:
+                       val = SOUND_MASK_VOLUME;
+                       break;
+               default:
+                       val = 0;
+                       printk(KERN_WARNING "omap1610-tsc2101: unknown mixer "
+        "read ioctl flag specified\n");
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (ret == 0)
+                       ret = put_user(val, (int __user *)arg);
+       }
+      out:
+       FN_OUT(0);
+       return ret;
+
+}
+
+/*********************************************************************************
+ *
+ * omap_set_samplerate()
+ *
+ ********************************************************************************/
+static int omap_set_samplerate(long sample_rate)
+{
+       u8 count = 0;
+       u16 data = 0;
+       int clkgdv = 0;
+       /* wait for any frame to complete */
+       udelay(125);
+
+       /* Search for the right sample rate */
+       while ((reg_info[count].sample_rate != sample_rate) &&
+              (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
+               count++;
+       }
+       if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
+               printk(KERN_ERR "Invalid Sample Rate %d requested\n",
+                      (int)sample_rate);
+               return -EPERM;
+       }
+
+       /* Set AC1 */
+       data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_1);
+       /*Clear prev settings */
+       data &= ~(AC1_DACFS(0x07) | AC1_ADCFS(0x07));
+       data |=
+           AC1_DACFS(reg_info[count].divisor) | AC1_ADCFS(reg_info[count].
+                                                          divisor);
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_1, data);
+
+       /* Set the AC3 */
+       data = audio_tsc2101_read(TSC2101_AUDIO_CTRL_3);
+       /*Clear prev settings */
+       data &= ~(AC3_REFFS | AC3_SLVMS);
+       data |= (reg_info[count].fs_44kHz) ? AC3_REFFS : 0;
+#ifdef TSC_MASTER
+       data |= AC3_SLVMS;
+#endif                         /* #ifdef TSC_MASTER */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_3, data);
+
+       /* program the PLLs */
+       if (reg_info[count].fs_44kHz) {
+               /* 44.1 khz - 12 MHz Mclk */
+               audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7));    /* PVAL 1; I_VAL 7 */
+               audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));    /* D_VAL 5264 */
+       } else {
+               /* 48 khz - 12 Mhz Mclk */
+               audio_tsc2101_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8));    /* PVAL 1; I_VAL 8 */
+               audio_tsc2101_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));     /* D_VAL 1920 */
+       }
+
+       audio_samplerate = sample_rate;
+
+       /* Set the sample rate */
+#ifndef TSC_MASTER
+       clkgdv =
+           DEFAULT_MCBSP_CLOCK / (sample_rate *
+                                  (DEFAULT_BITPERSAMPLE * 2 - 1));
+       if (clkgdv)
+               initial_config.srgr1 =
+                   (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
+       else
+               return (1);
+
+       /* Stereo Mode */
+       initial_config.srgr2 =
+           (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
+#else
+       initial_config.srgr1 =
+           (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
+       initial_config.srgr2 =
+           ((GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1)));
+
+#endif                         /* end of #ifdef TSC_MASTER */
+       omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
+
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * omap_tsc2101_initialize() [hw_init() ]
+ *
+ ********************************************************************************/
+static void omap_tsc2101_initialize(void *dummy)
+{
+
+       DPRINTK("omap_tsc2101_initialize entry\n");
+
+       /* initialize with default sample rate */
+       audio_samplerate = AUDIO_RATE_DEFAULT;
+
+       omap_mcbsp_request(AUDIO_MCBSP);
+
+       /* if configured, then stop mcbsp */
+       omap_mcbsp_stop(AUDIO_MCBSP);
+
+       omap_tsc2101_enable();
+
+       omap_mcbsp_config(AUDIO_MCBSP, &initial_config);
+       omap_mcbsp_start(AUDIO_MCBSP);
+       tsc2101_configure();
+
+#ifdef TEST_KEYCLICK
+       tsc2101_testkeyclick();
+#endif
+
+#ifdef TONE_GEN
+       toneGen();
+#endif
+
+       DPRINTK("omap_tsc2101_initialize exit\n");
+}
+
+/*********************************************************************************
+ *
+ * omap_tsc2101_shutdown() [hw_shutdown() ]
+ *
+ ********************************************************************************/
+static void omap_tsc2101_shutdown(void *dummy)
+{
+       /*
+          Turn off codec after it is done.
+          Can't do it immediately, since it may still have
+          buffered data.
+
+          Wait 20ms (arbitrary value) and then turn it off.
+        */
+
+       FN_IN;
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(2);
+
+       omap_mcbsp_stop(AUDIO_MCBSP);
+       omap_mcbsp_free(AUDIO_MCBSP);
+
+       audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
+                           ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
+
+       omap_tsc2101_disable();
+
+       FN_OUT(0);
+}
+
+/*********************************************************************************
+ *
+ * tsc2101_configure
+ *
+ ********************************************************************************/
+static void tsc2101_configure(void)
+{
+       FN_IN;
+
+       audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
+
+       /*Mute Analog Sidetone */
+       /*Select MIC_INHED input for headset */
+       /*Cell Phone In not connected */
+       audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
+                           MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
+
+       /* Set record source */
+       tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
+
+       /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
+       /* 1dB AGC hysteresis */
+       /* MICes bias 2V */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
+
+       /* Set codec output volume */
+       audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
+
+       /* DAC left and right routed to SPK2 */
+       /* SPK1/2 unmuted */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
+                           AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
+                           AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
+                           AC5_HDSCPTC);
+
+       /* OUT8P/N muted, CPOUT muted */
+
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
+                           AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
+                           AC6_VGNDSCPTC);
+
+       /* Headset/Hook switch detect disabled */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
+
+       /* Left line input volume control */
+       tsc2101_update(SET_LINE, tsc2101_local.line);
+
+       /* mic input volume control */
+       tsc2101_update(SET_MIC, tsc2101_local.mic);
+
+       /* Left/Right headphone channel volume control */
+       /* Zero-cross detect on */
+       tsc2101_update(SET_VOLUME, tsc2101_local.volume);
+
+       /* clock configuration */
+       omap_set_samplerate(audio_samplerate);
+
+#ifdef TSC_DUMP_REGISTERS
+       tsc2101_dumpRegisters();
+#endif
+
+       FN_OUT(0);
+}
+
+#ifdef PROC_SUPPORT
+static void tsc2101_start(void)
+{
+       FN_IN;
+
+       audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL, 0x0000);
+
+       /*Mute Analog Sidetone */
+       /*Select MIC_INHED input for headset */
+       /*Cell Phone In not connected */
+       audio_tsc2101_write(TSC2101_MIXER_PGA_CTRL,
+                           MPC_ASTMU | MPC_ASTG(0x40) | MPC_MICADC);
+
+       /* Set record source */
+       tsc2101_update(SET_RECSRC, tsc2101_local.recsrc);
+
+       /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
+       /* 1dB AGC hysteresis */
+       /* MICes bias 2V */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
+
+       /* Set codec output volume */
+       audio_tsc2101_write(TSC2101_DAC_GAIN_CTRL, 0x0000);
+
+       /* DAC left and right routed to SPK2 */
+       /* SPK1/2 unmuted */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_5,
+                           AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
+                           AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
+                           AC5_HDSCPTC);
+
+       /* OUT8P/N muted, CPOUT muted */
+
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_6,
+                           AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
+                           AC6_VGNDSCPTC);
+
+       /* Headset/Hook switch detect disabled */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_7, 0x0000);
+
+       /* Left line input volume control */
+       tsc2101_update(SET_LINE, tsc2101_local.line);
+
+       /* mic input volume control */
+       tsc2101_update(SET_MIC, tsc2101_local.mic);
+
+       /* Left/Right headphone channel volume control */
+       /* Zero-cross detect on */
+       tsc2101_update(SET_VOLUME, tsc2101_local.volume);
+
+       FN_OUT(0);
+
+}
+#endif
+
+/******************************************************************************************
+ *
+ * All generic ioctl's are handled by audio_ioctl() [File: omap-audio.c]. This
+ * routine handles some platform specific ioctl's
+ *
+ ******************************************************************************************/
+static int
+omap_tsc2101_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+       long val;
+       int ret = 0;
+
+       DPRINTK(" 0x%08x\n", cmd);
+
+       /*
+        * These are platform dependent ioctls which are not handled by the
+        * generic omap-audio module.
+        */
+       switch (cmd) {
+       case SNDCTL_DSP_STEREO:
+               ret = get_user(val, (int __user *)arg);
+               if (ret)
+                       return ret;
+               /* the AIC23 is stereo only */
+               ret = (val == 0) ? -EINVAL : 1;
+               FN_OUT(1);
+               return put_user(ret, (int __user *)arg);
+
+       case SNDCTL_DSP_CHANNELS:
+       case SOUND_PCM_READ_CHANNELS:
+               /* the AIC23 is stereo only */
+               FN_OUT(2);
+               return put_user(2, (long __user *)arg);
+
+       case SNDCTL_DSP_SPEED:
+               ret = get_user(val, (long __user *)arg);
+               if (ret)
+                       break;
+               ret = omap_set_samplerate(val);
+               if (ret)
+                       break;
+               /* fall through */
+
+       case SOUND_PCM_READ_RATE:
+               FN_OUT(3);
+               return put_user(audio_samplerate, (long __user *)arg);
+
+       case SOUND_PCM_READ_BITS:
+       case SNDCTL_DSP_SETFMT:
+       case SNDCTL_DSP_GETFMTS:
+               /* we can do 16-bit only */
+               FN_OUT(4);
+               return put_user(AFMT_S16_LE, (long __user *)arg);
+
+       default:
+               /* Maybe this is meant for the mixer (As per OSS Docs) */
+               FN_OUT(5);
+               return mixer_ioctl(inode, file, cmd, arg);
+       }
+
+       FN_OUT(0);
+       return ret;
+}
+
+/*********************************************************************************
+ *
+ * module_probe for TSC2101
+ *
+ ********************************************************************************/
+static int omap_tsc2101_probe(void)
+{
+       FN_IN;
+
+       /* Get the fops from audio oss driver */
+       if (!(omap_audio_fops = audio_get_fops())) {
+               printk(KERN_ERR "Unable to Get the FOPs of Audio OSS driver\n");
+               audio_unregister_codec(&tsc2101_state);
+               return -EPERM;
+       }
+
+       /* register devices */
+       audio_dev_id = register_sound_dsp(omap_audio_fops, -1);
+       mixer_dev_id = register_sound_mixer(&omap_mixer_fops, -1);
+
+#ifdef PROC_SUPPORT
+       create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
+                              NULL /* parent dir */ ,
+                              codec_start, NULL /* client data */ );
+
+       create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
+                              NULL /* parent dir */ ,
+                              codec_stop, NULL /* client data */ );
+#endif
+
+       /* Announcement Time */
+       printk(KERN_INFO PLATFORM_NAME " " CODEC_NAME
+              " Audio support initialized\n");
+
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * Module Remove for TSC2101
+ *
+ ********************************************************************************/
+static void omap_tsc2101_remove(void)
+{
+       FN_IN;
+       /* Un-Register the codec with the audio driver */
+       unregister_sound_dsp(audio_dev_id);
+       unregister_sound_mixer(mixer_dev_id);
+
+#ifdef PROC_SUPPORT
+       remove_proc_entry(PROC_START_FILE, NULL);
+       remove_proc_entry(PROC_STOP_FILE, NULL);
+#endif
+       FN_OUT(0);
+
+}
+
+/*********************************************************************************
+ *
+ * Module Suspend for TSC2101
+ *
+ ********************************************************************************/
+static int omap_tsc2101_suspend(void)
+{
+
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * Module Resume for TSC2101
+ *
+ ********************************************************************************/
+static int omap_tsc2101_resume(void)
+{
+
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * module_init for TSC2101
+ *
+ ********************************************************************************/
+static int __init audio_tsc2101_init(void)
+{
+
+       int err = 0;
+       FN_IN;
+
+       if (machine_is_omap_osk() || machine_is_omap_innovator())
+               return -ENODEV;
+
+       /* register the codec with the audio driver */
+       if ((err = audio_register_codec(&tsc2101_state))) {
+               printk(KERN_ERR
+                      "Failed to register TSC driver with Audio OSS Driver\n");
+       }
+       FN_OUT(err);
+       return err;
+}
+
+/*********************************************************************************
+ *
+ * module_exit for TSC2101
+ *
+ ********************************************************************************/
+static void __exit audio_tsc2101_exit(void)
+{
+
+       FN_IN;
+       (void)audio_unregister_codec(&tsc2101_state);
+       FN_OUT(0);
+       return;
+}
+
+/**************************** DEBUG FUNCTIONS ***********************************/
+
+/*********************************************************************************
+ * TEST_KEYCLICK:
+ * This is a test to generate various keyclick sound on tsc.
+ * verifies if the tsc and the spi interfaces are operational.
+ *
+ ********************************************************************************/
+#ifdef TEST_KEYCLICK
+void tsc2101_testkeyclick(void)
+{
+       u8 freq = 0;
+       u16 old_reg_val, reg_val;
+       u32 uDummyVal = 0;
+       u32 uTryVal = 0;
+
+       old_reg_val = audio_tsc2101_read(TSC2101_AUDIO_CTRL_2);
+
+       /* Keyclick active, max amplitude and longest key click len(32 period) */
+       printk(KERN_INFO " TESTING KEYCLICK\n Listen carefully NOW....\n");
+       printk(KERN_INFO " OLD REG VAL=0x%x\n", old_reg_val);
+       /* try all frequencies */
+       for (; freq < 8; freq++) {
+               /* Keyclick active, max amplitude and longest key click len(32 period) */
+               reg_val = old_reg_val | AC2_KCLAC(0x7) | AC2_KCLLN(0xF);
+               uDummyVal = 0;
+               uTryVal = 0;
+               printk(KERN_INFO "\n\nTrying frequency %d reg val= 0x%x\n",
+                      freq, reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
+               audio_tsc2101_write(TSC2101_AUDIO_CTRL_2,
+                                   reg_val | AC2_KCLFRQ(freq) | AC2_KCLEN);
+               printk("DONE. Wait 10 ms ...\n");
+               /* wait till the kclk bit is auto cleared! time out also to be considered. */
+               while (audio_tsc2101_read(TSC2101_AUDIO_CTRL_2) & AC2_KCLEN) {
+                       udelay(3);
+                       uTryVal++;
+                       if (uTryVal > 2000) {
+                               printk(KERN_ERR
+                                      "KEYCLICK TIMED OUT! freq val=%d, POSSIBLE ERROR!\n",
+                                      freq);
+                               printk(KERN_INFO
+                                      "uTryVal == %d: Read back new reg val= 0x%x\n",
+                                      uTryVal,
+                                      audio_tsc2101_read
+                                      (TSC2101_AUDIO_CTRL_2));
+                               /* clear */
+                               audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, 0x00);
+                               break;
+                       }
+               }
+       }
+       /* put the old value back */
+       audio_tsc2101_write(TSC2101_AUDIO_CTRL_2, old_reg_val);
+       printk(KERN_INFO " KEYCLICK TEST COMPLETE\n");
+
+}                              /* End of tsc2101_testkeyclick */
+
+#endif                         /* TEST_KEYCLICK */
+
+/*********************************************************************************
+ * TONEGEN:
+ * This is a test to generate a rather unpleasant sound..
+ * verifies if the mcbsp is active (requires MCBSP_DIRECT_RW to be active on McBSP)
+ *
+ ********************************************************************************/
+#ifdef TONE_GEN
+/* Generates a shrill tone */
+u16 tone[] = {
+       0x0ce4, 0x0ce4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
+       0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
+       0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
+       0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
+       0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
+       0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
+       0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
+       0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
+       0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
+       0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
+       0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
+       0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
+       0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
+       0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
+       0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
+       0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
+       0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
+       0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
+       0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
+       0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
+       0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
+       0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000,
+       0x0CE4, 0x0CE4, 0x1985, 0x1985, 0x25A1, 0x25A1, 0x30FD, 0x30FE,
+       0x3B56, 0x3B55, 0x447A, 0x447A, 0x4C3B, 0x4C3C, 0x526D, 0x526C,
+       0x56F1, 0x56F1, 0x59B1, 0x59B1, 0x5A9E, 0x5A9D, 0x59B1, 0x59B2,
+       0x56F3, 0x56F2, 0x526D, 0x526D, 0x4C3B, 0x4C3B, 0x447C, 0x447C,
+       0x3B5A, 0x3B59, 0x30FE, 0x30FE, 0x25A5, 0x25A6, 0x1989, 0x198A,
+       0x0CE5, 0x0CE3, 0x0000, 0x0000, 0xF31C, 0xF31C, 0xE677, 0xE676,
+       0xDA5B, 0xDA5B, 0xCF03, 0xCF03, 0xC4AA, 0xC4AA, 0xBB83, 0xBB83,
+       0xB3C5, 0xB3C5, 0xAD94, 0xAD94, 0xA90D, 0xA90E, 0xA64F, 0xA64E,
+       0xA562, 0xA563, 0xA64F, 0xA64F, 0xA910, 0xA90F, 0xAD93, 0xAD94,
+       0xB3C4, 0xB3C4, 0xBB87, 0xBB86, 0xC4AB, 0xC4AB, 0xCF03, 0xCF03,
+       0xDA5B, 0xDA5A, 0xE67B, 0xE67B, 0xF31B, 0xF3AC, 0x0000, 0x0000
+};
+
+void toneGen(void)
+{
+       int count = 0;
+       int ret = 0;
+       printk(KERN_INFO "TONE GEN TEST :");
+
+       for (count = 0; count < 5000; count++) {
+               int bytes;
+               for (bytes = 0; bytes < sizeof(tone) / 2; bytes++) {
+                       ret = omap_mcbsp_pollwrite(AUDIO_MCBSP, tone[bytes]);
+                       if (ret == -1) {
+                               /* retry */
+                               bytes--;
+                       } else if (ret == -2) {
+                               printk(KERN_INFO "ERROR:bytes=%d\n", bytes);
+                               return;
+                       }
+               }
+       }
+       printk(KERN_INFO "SUCCESS\n");
+}
+
+#endif                         /* End of TONE_GEN */
+
+/*********************************************************************************
+ *
+ * TSC_DUMP_REGISTERS:
+ * This will dump the entire register set of Page 2 tsc2101. 
+ * Useful for major goof ups
+ *
+ ********************************************************************************/
+#ifdef TSC_DUMP_REGISTERS
+static void tsc2101_dumpRegisters(void)
+{
+       int i = 0;
+       u16 data = 0;
+       printk("TSC 2101 Register dump for Page 2 \n");
+       for (i = 0; i < 0x27; i++) {
+               data = audio_tsc2101_read(i);
+               printk(KERN_INFO "Register[%x]=0x%04x\n", i, data);
+
+       }
+}
+#endif                         /* End of #ifdef TSC_DUMP_REGISTERS */
+
+#ifdef PROC_SUPPORT
+static int codec_start(char *buf, char **start, off_t offset, int count,
+                      int *eof, void *data)
+{
+       omap_tsc2101_enable();
+       tsc2101_start();
+       printk("Codec initialization done.\n");
+       return 0;
+}
+static int codec_stop(char *buf, char **start, off_t offset, int count,
+                     int *eof, void *data)
+{
+
+       omap_tsc2101_disable();
+       audio_tsc2101_write(TSC2101_CODEC_POWER_CTRL,
+                           ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
+       printk("Codec shutdown.\n");
+       return 0;
+}
+#endif
+
+/*********************************************************************************
+ *
+ * Other misc management, registration etc
+ *
+ ********************************************************************************/
+module_init(audio_tsc2101_init);
+module_exit(audio_tsc2101_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION
+    ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
+MODULE_LICENSE("GPL");
diff --git a/sound/oss/omap-audio.c b/sound/oss/omap-audio.c
new file mode 100644 (file)
index 0000000..afcf98d
--- /dev/null
@@ -0,0 +1,1168 @@
+/*
+ * linux/sound/oss/omap-audio.c
+ *
+ * Common audio handling for the OMAP processors
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004/08/12   Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms
+ *
+ * 2004-11-01   Nishanth Menon - modified to support 16xx and 17xx 
+ *                platform multi channel chaining.
+ *
+ * 2004-11-04   Nishanth Menon - Added support for power management
+ *
+ * 2004-12-17   Nishanth Menon - Provided proper module handling support
+ */
+
+/***************************** INCLUDES ************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/completion.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+
+#include "omap-audio-dma-intfc.h"
+#include "omap-audio.h"
+
+/***************************** MACROS ************************************/
+
+#undef DEBUG
+//#define DEBUG
+#ifdef DEBUG
+#define DPRINTK  printk
+#define FN_IN printk("[omap_audio.c:[%s] start\n", __FUNCTION__)
+#define FN_OUT(n) printk("[omap_audio.c:[%s] end(%d)\n", __FUNCTION__ , n)
+#else
+#define DPRINTK( x... )
+#define FN_IN
+#define FN_OUT(x)
+#endif
+
+#define OMAP_AUDIO_NAME                "omap-audio"
+#define AUDIO_NBFRAGS_DEFAULT  8
+#define AUDIO_FRAGSIZE_DEFAULT 8192
+
+/* HACK ALERT!: These values will bave to be tuned as this is a trade off b/w
+ * Sampling Rate vs buffer size and delay we are prepared to do before giving up
+ */
+#define MAX_QUEUE_FULL_RETRIES 1000000
+#define QUEUE_WAIT_TIME        10
+
+#define AUDIO_ACTIVE(state)    ((state)->rd_ref || (state)->wr_ref)
+
+#define SPIN_ADDR              (dma_addr_t)0
+#define SPIN_SIZE              2048
+
+/***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
+
+static int audio_write(struct file *file, const char __user *buffer,
+                      size_t count, loff_t * ppos);
+
+static int audio_read(struct file *file, char __user *buffer, size_t count,
+                     loff_t * ppos);
+
+static int audio_mmap(struct file *file, struct vm_area_struct *vma);
+
+static unsigned int audio_poll(struct file *file,
+                              struct poll_table_struct *wait);
+
+static loff_t audio_llseek(struct file *file, loff_t offset, int origin);
+
+static int audio_ioctl(struct inode *inode, struct file *file, uint cmd,
+                      ulong arg);
+
+static int audio_open(struct inode *inode, struct file *file);
+
+static int audio_release(struct inode *inode, struct file *file);
+
+static int audio_probe(struct device *dev);
+
+static int audio_remove(struct device *dev);
+
+static void audio_shutdown(struct device *dev);
+
+static int audio_suspend(struct device *dev, pm_message_t mesg, u32 level);
+
+static int audio_resume(struct device *dev, u32 level);
+
+static void audio_free(struct device *dev);
+
+/***************************** Data Structures **********************************/
+
+/*
+ * The function pointer set to be registered by the codec.
+ */
+static audio_state_t audio_state = { NULL };
+
+/* DMA Call back function */
+static dma_callback_t audio_dma_callback = NULL;
+
+/* File Ops structure */
+static struct file_operations omap_audio_fops = {
+       .open           = audio_open,
+       .release        = audio_release,
+       .write          = audio_write,
+       .read           = audio_read,
+       .mmap           = audio_mmap,
+       .poll           = audio_poll,
+       .ioctl          = audio_ioctl,
+       .llseek         = audio_llseek,
+       .owner          = THIS_MODULE
+};
+
+/* Driver information */
+static struct device_driver omap_audio_driver = {
+       .name           = OMAP_AUDIO_NAME,
+       .bus            = &platform_bus_type,
+       .probe          = audio_probe,
+       .remove         = audio_remove,
+       .suspend        = audio_suspend,
+       .resume         = audio_resume,
+       .shutdown       = audio_shutdown,
+};
+
+/* Device Information */
+static struct platform_device omap_audio_device = {
+       .name = OMAP_AUDIO_NAME,
+       .dev = {
+               .driver_data = &audio_state,
+               .release = audio_free,
+               },
+       .id = 0,
+};
+
+/***************************** GLOBAL FUNCTIONs **********************************/
+
+/* Power Management Functions for Linux Device Model  */
+/* DEBUG PUPOSES ONLY! */
+#ifdef CONFIG_PM
+//#undef CONFIG_PM
+#endif
+
+#ifdef CONFIG_PM
+/*********************************************************************************
+ *
+ * audio_ldm_suspend(): Suspend operation
+ *
+ *********************************************************************************/
+static int audio_ldm_suspend(void *data)
+{
+       audio_state_t *state = data;
+
+       FN_IN;
+
+       /* 
+        * Reject the suspend request if we are already actively transmitting data 
+        * Rationale: We dont want to be suspended while in the middle of a call!
+        */
+       if (AUDIO_ACTIVE(state) && state->hw_init) {
+               printk(KERN_ERR "Audio device Active, Cannot Suspend");
+               return -EPERM;
+#if 0
+               /* NOTE:
+                * This Piece of code is commented out in hope
+                * That one day we would need to suspend the device while 
+                * audio operations are in progress and resume the operations
+                * once the resume is done.
+                * This is just a sample implementation of how it could be done.
+                * Currently NOT SUPPORTED
+                */
+               audio_stream_t *is = state->input_stream;
+               audio_stream_t *os = state->output_stream;
+               int stopstate;
+               if (is && is->buffers) {
+                       printk("IS Suspend\n");
+                       stopstate = is->stopped;
+                       audio_stop_dma(is);
+                       DMA_CLEAR(is);
+                       is->dma_spinref = 0;
+                       is->stopped = stopstate;
+               }
+               if (os && os->buffers) {
+                       printk("OS Suspend\n");
+                       stopstate = os->stopped;
+                       audio_stop_dma(os);
+                       DMA_CLEAR(os);
+                       os->dma_spinref = 0;
+                       os->stopped = stopstate;
+               }
+#endif
+       }
+
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * audio_ldm_resume(): Resume Operations
+ *
+ *********************************************************************************/
+static int audio_ldm_resume(void *data)
+{
+       audio_state_t *state = data;
+
+       FN_IN;
+       if (AUDIO_ACTIVE(state) && state->hw_init) {
+               /* Should never occur - since we never suspend with active state */
+               BUG();
+               return -EPERM;
+#if 0
+               /* NOTE:
+                * This Piece of code is commented out in hope
+                * That one day we would need to suspend the device while 
+                * audio operations are in progress and resume the operations
+                * once the resume is done.
+                * This is just a sample implementation of how it could be done.
+                * Currently NOT SUPPORTED
+                */
+               audio_stream_t *is = state->input_stream;
+               audio_stream_t *os = state->output_stream;
+               if (os && os->buffers) {
+                       printk("OS Resume\n");
+                       audio_reset(os);
+                       audio_process_dma(os);
+               }
+               if (is && is->buffers) {
+                       printk("IS Resume\n");
+                       audio_reset(is);
+                       audio_process_dma(is);
+               }
+#endif
+       }
+       FN_OUT(0);
+       return 0;
+}
+#endif                         /* End of #ifdef CONFIG_PM */
+
+/*********************************************************************************
+ *
+ * audio_free(): The Audio driver release function
+ * This is a dummy function required by the platform driver
+ *
+ *********************************************************************************/
+static void audio_free(struct device *dev)
+{
+       /* Nothing to Release! */
+}
+
+/*********************************************************************************
+ *
+ * audio_probe(): The Audio driver probe function
+ * WARNING!!!!  : It is expected that the codec would have registered with us by now
+ *
+ *********************************************************************************/
+static int audio_probe(struct device *dev)
+{
+       int ret;
+       FN_IN;
+       if (!audio_state.hw_probe) {
+               printk(KERN_ERR "Probe Function Not Registered\n");
+               return -ENODEV;
+       }
+       ret = audio_state.hw_probe();
+       FN_OUT(ret);
+       return ret;
+}
+
+/*********************************************************************************
+ *
+ * audio_remove() Function to handle removal operations
+ *
+ *********************************************************************************/
+static int audio_remove(struct device *dev)
+{
+       FN_IN;
+       if (audio_state.hw_remove) {
+               audio_state.hw_remove();
+       }
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * audio_shutdown(): Function to handle shutdown operations
+ *
+ *********************************************************************************/
+static void audio_shutdown(struct device *dev)
+{
+       FN_IN;
+       if (audio_state.hw_cleanup) {
+               audio_state.hw_cleanup();
+       }
+       FN_OUT(0);
+       return;
+}
+
+/*********************************************************************************
+ *
+ * audio_suspend(): Function to handle suspend operations 
+ *
+ *********************************************************************************/
+static int audio_suspend(struct device *dev, pm_message_t mesg, u32 level)
+{
+       int ret = 0;
+
+#ifdef CONFIG_PM
+       void *data = dev->driver_data;
+       FN_IN;
+       if (level != SUSPEND_POWER_DOWN) {
+               return 0;
+       }
+       if (audio_state.hw_suspend) {
+               ret = audio_ldm_suspend(data);
+               if (ret == 0)
+                       ret = audio_state.hw_suspend();
+       }
+       if (ret) {
+               printk(KERN_INFO "Audio Suspend Failed \n");
+       } else {
+               printk(KERN_INFO "Audio Suspend Success \n");
+       }
+#endif                         /* CONFIG_PM */
+
+       FN_OUT(ret);
+       return ret;
+}
+
+/*********************************************************************************
+ *
+ * audio_resume(): Function to handle resume operations
+ *
+ *********************************************************************************/
+static int audio_resume(struct device *dev, u32 level)
+{
+       int ret = 0;
+
+#ifdef CONFIG_PM
+       void *data = dev->driver_data;
+       FN_IN;
+       if (level != RESUME_POWER_ON) {
+               return 0;
+       }
+       if (audio_state.hw_resume) {
+               ret = audio_ldm_resume(data);
+               if (ret == 0)
+                       ret = audio_state.hw_resume();
+       }
+       if (ret) {
+               printk(KERN_INFO " Audio Resume Failed \n");
+       } else {
+               printk(KERN_INFO " Audio Resume Success \n");
+       }
+#endif                         /* CONFIG_PM */
+
+       FN_OUT(ret);
+       return ret;
+}
+
+/*********************************************************************************
+ *
+ * audio_get_fops(): Return the fops required to get the function pointers of 
+ *                   OMAP Audio Driver
+ *
+ *********************************************************************************/
+struct file_operations *audio_get_fops(void)
+{
+       FN_IN;
+       FN_OUT(0);
+       return &omap_audio_fops;
+}
+
+/*********************************************************************************
+ *
+ * audio_register_codec(): Register a Codec fn points using this function
+ * WARNING!!!!!          : Codecs should ensure that they do so! no sanity checks
+ *                         during runtime is done due to obvious performance 
+ *                         penalties.
+ *
+ *********************************************************************************/
+int audio_register_codec(audio_state_t * codec_state)
+{
+       int ret;
+       FN_IN;
+
+       /* We dont handle multiple codecs now */
+       if (audio_state.hw_init) {
+               printk(KERN_ERR " Codec Already registered\n");
+               return -EPERM;
+       }
+
+       /* Grab the dma Callback */
+       audio_dma_callback = audio_get_dma_callback();
+       if (!audio_dma_callback) {
+               printk(KERN_ERR "Unable to get call back function\n");
+               return -EPERM;
+       }
+
+       /* Sanity checks */
+       if (!codec_state) {
+               printk(KERN_ERR "NULL ARGUMENT!\n");
+               return -EPERM;
+       }
+
+       if (!codec_state->hw_probe || !codec_state->hw_init
+           || !codec_state->hw_shutdown || !codec_state->client_ioctl) {
+               printk(KERN_ERR
+                      "Required Fn Entry point Missing probe=%p init=%p,down=%p,ioctl=%p!\n",
+                      codec_state->hw_probe, codec_state->hw_init,
+                      codec_state->hw_shutdown, codec_state->client_ioctl);
+               return -EPERM;
+       }
+
+       memcpy(&audio_state, codec_state, sizeof(audio_state_t));
+       sema_init(&audio_state.sem, 1);
+
+       ret = platform_device_register(&omap_audio_device);
+       if (ret != 0) {
+               printk(KERN_ERR "Platform dev_register failed =%d\n", ret);
+               ret = -ENODEV;
+               goto register_out;
+       }
+
+       ret = driver_register(&omap_audio_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Device Register failed =%d\n", ret);
+               ret = -ENODEV;
+               platform_device_unregister(&omap_audio_device);
+               goto register_out;
+       }
+
+      register_out:
+
+       FN_OUT(ret);
+       return ret;
+}
+
+/*********************************************************************************
+ *
+ * audio_unregister_codec(): Un-Register a Codec using this function
+ *
+ *********************************************************************************/
+int audio_unregister_codec(audio_state_t * codec_state)
+{
+       FN_IN;
+
+       /* We dont handle multiple codecs now */
+       if (!audio_state.hw_init) {
+               printk(KERN_ERR " No Codec registered\n");
+               return -EPERM;
+       }
+       /* Security check */
+       if (audio_state.hw_init != codec_state->hw_init) {
+               printk(KERN_ERR
+                      " Attempt to unregister codec which was not registered with us\n");
+               return -EPERM;
+       }
+
+       driver_unregister(&omap_audio_driver);
+       platform_device_unregister(&omap_audio_device);
+
+       memset(&audio_state, 0, sizeof(audio_state_t));
+
+       FN_OUT(0);
+       return 0;
+}
+
+/***************************** MODULES SPECIFIC FUNCTION *************************/
+
+/*********************************************************************************
+ *
+ * audio_write(): Exposed to write() call
+ *
+ *********************************************************************************/
+static int
+audio_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t * ppos)
+{
+       const char __user *buffer0 = buffer;
+       audio_state_t *state = file->private_data;
+       audio_stream_t *s = state->output_stream;
+       int chunksize, ret = 0;
+
+       DPRINTK("audio_write: count=%d\n", count);
+       if (*ppos != file->f_pos) {
+               printk("FPOS not ppos ppos=0x%x fpos =0x%x\n", (u32) * ppos,
+                      (u32) file->f_pos);
+               return -ESPIPE;
+       }
+       if (s->mapped) {
+               printk("s already mapped\n");
+               return -ENXIO;
+       }
+       if (!s->buffers && audio_setup_buf(s)) {
+               printk("NO MEMORY\n");
+               return -ENOMEM;
+       }
+
+       while (count > 0) {
+               audio_buf_t *b = &s->buffers[s->usr_head];
+
+               /* Wait for a buffer to become free */
+               if (file->f_flags & O_NONBLOCK) {
+                       ret = -EAGAIN;
+                       if (!s->wfc.done)
+                               break;
+               }
+               ret = -ERESTARTSYS;
+               if (wait_for_completion_interruptible(&s->wfc))
+                       break;
+
+               /* Feed the current buffer */
+               chunksize = s->fragsize - b->offset;
+               if (chunksize > count)
+                       chunksize = count;
+               DPRINTK("write %d to %d\n", chunksize, s->usr_head);
+               if (copy_from_user(b->data + b->offset, buffer, chunksize)) {
+                       printk(KERN_ERR "Audio: CopyFrom User failed \n");
+                       complete(&s->wfc);
+                       return -EFAULT;
+               }
+
+               buffer += chunksize;
+               count -= chunksize;
+               b->offset += chunksize;
+
+               if (b->offset < s->fragsize) {
+                       complete(&s->wfc);
+                       break;
+               }
+
+               /* Update pointers and send current fragment to DMA */
+               b->offset = 0;
+               if (++s->usr_head >= s->nbfrags)
+                       s->usr_head = 0;
+               /* Add the num of frags pending */
+               s->pending_frags++;
+               s->active = 1;
+
+               audio_process_dma(s);
+
+       }
+
+       if ((buffer - buffer0))
+               ret = buffer - buffer0;
+       DPRINTK("audio_write: return=%d\n", ret);
+       return ret;
+}
+
+/*********************************************************************************
+ *
+ * audio_read(): Exposed as read() function
+ *
+ *********************************************************************************/
+static int
+audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
+{
+       char __user *buffer0 = buffer;
+       audio_state_t *state = file->private_data;
+       audio_stream_t *s = state->input_stream;
+       int chunksize, ret = 0;
+       unsigned long flags;
+
+       DPRINTK("audio_read: count=%d\n", count);
+
+       if (*ppos != file->f_pos) {
+               printk("AudioRead - FPOS not ppos ppos=0x%x fpos =0x%x\n",
+                      (u32) * ppos, (u32) file->f_pos);
+               return -ESPIPE;
+       }
+       if (s->mapped) {
+               printk("AudioRead - s already mapped\n");
+               return -ENXIO;
+       }
+
+       if (!s->active) {
+               if (!s->buffers && audio_setup_buf(s)) {
+                       printk("AudioRead - No Memory\n");
+                       return -ENOMEM;
+               }
+               audio_prime_rx(state);
+       }
+
+       while (count > 0) {
+               audio_buf_t *b = &s->buffers[s->usr_head];
+
+               /* Wait for a buffer to become full */
+               if (file->f_flags & O_NONBLOCK) {
+                       ret = -EAGAIN;
+                       if (!s->wfc.done)
+                               break;
+               }
+               ret = -ERESTARTSYS;
+               if (wait_for_completion_interruptible(&s->wfc))
+                       break;
+
+               /* Grab data from the current buffer */
+               chunksize = s->fragsize - b->offset;
+               if (chunksize > count)
+                       chunksize = count;
+               DPRINTK("read %d from %d\n", chunksize, s->usr_head);
+               if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
+                       complete(&s->wfc);
+                       return -EFAULT;
+               }
+               buffer += chunksize;
+               count -= chunksize;
+               b->offset += chunksize;
+               if (b->offset < s->fragsize) {
+                       complete(&s->wfc);
+                       break;
+               }
+
+               /* Update pointers and return current fragment to DMA */
+               local_irq_save(flags);
+               b->offset = 0;
+               if (++s->usr_head >= s->nbfrags)
+                       s->usr_head = 0;
+
+               s->pending_frags++;
+               local_irq_restore(flags);
+               audio_process_dma(s);
+
+       }
+
+       if ((buffer - buffer0))
+               ret = buffer - buffer0;
+       DPRINTK("audio_read: return=%d\n", ret);
+       return ret;
+}
+
+/*********************************************************************************
+ *
+ * audio_mmap(): Exposed as mmap Function
+ * !!WARNING: Still under development
+ *
+ *********************************************************************************/
+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       audio_state_t *state = file->private_data;
+       audio_stream_t *s;
+       unsigned long size, vma_addr;
+       int i, ret;
+
+       FN_IN;
+       if (vma->vm_pgoff != 0)
+               return -EINVAL;
+
+       if (vma->vm_flags & VM_WRITE) {
+               if (!state->wr_ref)
+                       return -EINVAL;;
+               s = state->output_stream;
+       } else if (vma->vm_flags & VM_READ) {
+               if (!state->rd_ref)
+                       return -EINVAL;
+               s = state->input_stream;
+       } else
+               return -EINVAL;
+
+       if (s->mapped)
+               return -EINVAL;
+       size = vma->vm_end - vma->vm_start;
+       if (size != s->fragsize * s->nbfrags)
+               return -EINVAL;
+       if (!s->buffers && audio_setup_buf(s))
+               return -ENOMEM;
+       vma_addr = vma->vm_start;
+       for (i = 0; i < s->nbfrags; i++) {
+               audio_buf_t *buf = &s->buffers[i];
+               if (!buf->master)
+                       continue;
+               ret =
+                   remap_pfn_range(vma, vma_addr, buf->dma_addr >> PAGE_SHIFT,
+                                   buf->master, vma->vm_page_prot);
+               if (ret)
+                       return ret;
+               vma_addr += buf->master;
+       }
+       s->mapped = 1;
+
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * audio_poll(): Exposed as poll function
+ *
+ *********************************************************************************/
+static unsigned int
+audio_poll(struct file *file, struct poll_table_struct *wait)
+{
+       audio_state_t *state = file->private_data;
+       audio_stream_t *is = state->input_stream;
+       audio_stream_t *os = state->output_stream;
+       unsigned int mask = 0;
+
+       DPRINTK("audio_poll(): mode=%s%s\n",
+               (file->f_mode & FMODE_READ) ? "r" : "",
+               (file->f_mode & FMODE_WRITE) ? "w" : "");
+
+       if (file->f_mode & FMODE_READ) {
+               /* Start audio input if not already active */
+               if (!is->active) {
+                       if (!is->buffers && audio_setup_buf(is))
+                               return -ENOMEM;
+                       audio_prime_rx(state);
+               }
+               poll_wait(file, &is->wq, wait);
+       }
+
+       if (file->f_mode & FMODE_WRITE) {
+               if (!os->buffers && audio_setup_buf(os))
+                       return -ENOMEM;
+               poll_wait(file, &os->wq, wait);
+       }
+
+       if (file->f_mode & FMODE_READ)
+               if ((is->mapped && is->bytecount > 0) ||
+                   (!is->mapped && is->wfc.done > 0))
+                       mask |= POLLIN | POLLRDNORM;
+
+       if (file->f_mode & FMODE_WRITE)
+               if ((os->mapped && os->bytecount > 0) ||
+                   (!os->mapped && os->wfc.done > 0))
+                       mask |= POLLOUT | POLLWRNORM;
+
+       DPRINTK("audio_poll() returned mask of %s%s\n",
+               (mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : "");
+
+       FN_OUT(mask);
+       return mask;
+}
+
+/*********************************************************************************
+ *
+ * audio_llseek(): Exposed as lseek() function.
+ *
+ *********************************************************************************/
+static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
+{
+       FN_IN;
+       FN_OUT(0);
+       return -ESPIPE;
+}
+
+/*********************************************************************************
+ *
+ * audio_ioctl(): Handles generic ioctls. If there is a request for something this
+ * fn cannot handle, its then given to client specific ioctl routine, that will take
+ * up platform specific requests
+ *
+ *********************************************************************************/
+static int
+audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+       audio_state_t *state = file->private_data;
+       audio_stream_t *os = state->output_stream;
+       audio_stream_t *is = state->input_stream;
+       long val;
+
+       DPRINTK(__FILE__ " audio_ioctl 0x%08x\n", cmd);
+
+       /* dispatch based on command */
+       switch (cmd) {
+       case OSS_GETVERSION:
+               return put_user(SOUND_VERSION, (int __user *)arg);
+
+       case SNDCTL_DSP_GETBLKSIZE:
+               if (file->f_mode & FMODE_WRITE)
+                       return put_user(os->fragsize, (int __user *)arg);
+               else
+                       return put_user(is->fragsize, (int __user *)arg);
+
+       case SNDCTL_DSP_GETCAPS:
+               val = DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP;
+               if (is && os)
+                       val |= DSP_CAP_DUPLEX;
+               FN_OUT(1);
+               return put_user(val, (int __user *)arg);
+
+       case SNDCTL_DSP_SETFRAGMENT:
+               if (get_user(val, (long __user *)arg)) {
+                       FN_OUT(2);
+                       return -EFAULT;
+               }
+               if (file->f_mode & FMODE_READ) {
+                       int ret = audio_set_fragments(is, val);
+                       if (ret < 0) {
+                               FN_OUT(3);
+                               return ret;
+                       }
+                       ret = put_user(ret, (int __user *)arg);
+                       if (ret) {
+                               FN_OUT(4);
+                               return ret;
+                       }
+               }
+               if (file->f_mode & FMODE_WRITE) {
+                       int ret = audio_set_fragments(os, val);
+                       if (ret < 0) {
+                               FN_OUT(5);
+                               return ret;
+                       }
+                       ret = put_user(ret, (int __user *)arg);
+                       if (ret) {
+                               FN_OUT(6);
+                               return ret;
+                       }
+               }
+               FN_OUT(7);
+               return 0;
+
+       case SNDCTL_DSP_SYNC:
+               FN_OUT(8);
+               return audio_sync(file);
+
+       case SNDCTL_DSP_SETDUPLEX:
+               FN_OUT(9);
+               return 0;
+
+       case SNDCTL_DSP_POST:
+               FN_OUT(10);
+               return 0;
+
+       case SNDCTL_DSP_GETTRIGGER:
+               val = 0;
+               if (file->f_mode & FMODE_READ && is->active && !is->stopped)
+                       val |= PCM_ENABLE_INPUT;
+               if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
+                       val |= PCM_ENABLE_OUTPUT;
+               FN_OUT(11);
+               return put_user(val, (int __user *)arg);
+
+       case SNDCTL_DSP_SETTRIGGER:
+               if (get_user(val, (int __user *)arg)) {
+                       FN_OUT(12);
+                       return -EFAULT;
+               }
+               if (file->f_mode & FMODE_READ) {
+                       if (val & PCM_ENABLE_INPUT) {
+                               unsigned long flags;
+                               if (!is->active) {
+                                       if (!is->buffers && audio_setup_buf(is)) {
+                                               FN_OUT(13);
+                                               return -ENOMEM;
+                                       }
+                                       audio_prime_rx(state);
+                               }
+                               local_irq_save(flags);
+                               is->stopped = 0;
+                               local_irq_restore(flags);
+                               audio_process_dma(is);
+
+                       } else {
+                               audio_stop_dma(is);
+                       }
+               }
+               if (file->f_mode & FMODE_WRITE) {
+                       if (val & PCM_ENABLE_OUTPUT) {
+                               unsigned long flags;
+                               if (!os->buffers && audio_setup_buf(os)) {
+                                       FN_OUT(14);
+                                       return -ENOMEM;
+                               }
+                               local_irq_save(flags);
+                               if (os->mapped && !os->pending_frags) {
+                                       os->pending_frags = os->nbfrags;
+                                       init_completion(&os->wfc);
+                                       os->wfc.done = 0;
+                                       os->active = 1;
+                               }
+                               os->stopped = 0;
+                               local_irq_restore(flags);
+                               audio_process_dma(os);
+
+                       } else {
+                               audio_stop_dma(os);
+                       }
+               }
+               FN_OUT(15);
+               return 0;
+
+       case SNDCTL_DSP_GETOPTR:
+       case SNDCTL_DSP_GETIPTR:
+               {
+                       count_info inf = { 0, };
+                       audio_stream_t *s =
+                           (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
+                       int bytecount, offset;
+                       unsigned long flags;
+
+                       if ((s == is && !(file->f_mode & FMODE_READ)) ||
+                           (s == os && !(file->f_mode & FMODE_WRITE))) {
+                               FN_OUT(16);
+                               return -EINVAL;
+                       }
+                       if (s->active) {
+                               local_irq_save(flags);
+                               offset = audio_get_dma_pos(s);
+                               inf.ptr = s->dma_tail * s->fragsize + offset;
+                               bytecount = s->bytecount + offset;
+                               s->bytecount = -offset;
+                               inf.blocks = s->fragcount;
+                               s->fragcount = 0;
+                               local_irq_restore(flags);
+                               if (bytecount < 0)
+                                       bytecount = 0;
+                               inf.bytes = bytecount;
+                       }
+                       FN_OUT(17);
+                       return copy_to_user((void __user *)arg, &inf, sizeof(inf));
+               }
+
+       case SNDCTL_DSP_GETOSPACE:
+       case SNDCTL_DSP_GETISPACE:
+               {
+                       audio_buf_info inf = { 0, };
+                       audio_stream_t *s =
+                           (cmd == SNDCTL_DSP_GETOSPACE) ? os : is;
+
+                       if ((s == is && !(file->f_mode & FMODE_READ)) ||
+                           (s == os && !(file->f_mode & FMODE_WRITE))) {
+                               FN_OUT(18);
+                               return -EINVAL;
+                       }
+                       if (!s->buffers && audio_setup_buf(s)) {
+                               FN_OUT(19);
+                               return -ENOMEM;
+                       }
+                       inf.bytes = s->wfc.done * s->fragsize;
+
+                       inf.fragments = inf.bytes / s->fragsize;
+                       inf.fragsize = s->fragsize;
+                       inf.fragstotal = s->nbfrags;
+                       FN_OUT(20);
+                       return copy_to_user((void __user *)arg, &inf, sizeof(inf));
+               }
+
+       case SNDCTL_DSP_NONBLOCK:
+               file->f_flags |= O_NONBLOCK;
+               FN_OUT(21);
+               return 0;
+
+       case SNDCTL_DSP_RESET:
+               if (file->f_mode & FMODE_READ) {
+                       audio_reset(is);
+                       if (state->need_tx_for_rx) {
+                               unsigned long flags;
+                               local_irq_save(flags);
+                               os->spin_idle = 0;
+                               local_irq_restore(flags);
+                       }
+               }
+               if (file->f_mode & FMODE_WRITE) {
+                       audio_reset(os);
+               }
+               FN_OUT(22);
+               return 0;
+
+       default:
+               /*
+                * Let the client of this module handle the
+                * non generic ioctls
+                */
+               FN_OUT(23);
+               return state->client_ioctl(inode, file, cmd, arg);
+       }
+
+       FN_OUT(0);
+       return 0;
+}
+
+/*********************************************************************************
+ *
+ * audio_open(): Exposed as open() function
+ *
+ *********************************************************************************/
+static int audio_open(struct inode *inode, struct file *file)
+{
+       audio_state_t *state = (&audio_state);
+       audio_stream_t *os = state->output_stream;
+       audio_stream_t *is = state->input_stream;
+       int err, need_tx_dma;
+       static unsigned char tsc2101_init_flag = 0;
+
+       FN_IN;
+
+       /* Lock the module */
+       if (!try_module_get(THIS_MODULE)) {
+               printk(KERN_CRIT "Failed to get module\n");
+               return -ESTALE;
+       }
+       /* Lock the codec module */
+       if (!try_module_get(state->owner)) {
+               printk(KERN_CRIT "Failed to get codec module\n");
+               module_put(THIS_MODULE);
+               return -ESTALE;
+       }
+
+       down(&state->sem);
+
+       /* access control */
+       err = -ENODEV;
+       if ((file->f_mode & FMODE_WRITE) && !os)
+               goto out;
+       if ((file->f_mode & FMODE_READ) && !is)
+               goto out;
+       err = -EBUSY;
+       if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
+               goto out;
+       if ((file->f_mode & FMODE_READ) && state->rd_ref)
+               goto out;
+       err = -EINVAL;
+       if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !os)
+               goto out;
+
+       /* request DMA channels */
+       need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
+                      ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
+       if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
+               need_tx_dma = 0;
+       if (need_tx_dma) {
+               DMA_REQUEST(err, os, audio_dma_callback);
+               if (err < 0)
+                       goto out;
+       }
+       if (file->f_mode & FMODE_READ) {
+               DMA_REQUEST(err, is, audio_dma_callback);
+               if (err < 0) {
+                       if (need_tx_dma)
+                               DMA_FREE(os);
+                       goto out;
+               }
+       }
+
+       /* now complete initialisation */
+       if (!AUDIO_ACTIVE(state)) {
+               if (state->hw_init && !tsc2101_init_flag) {
+                       state->hw_init(state->data);
+                       tsc2101_init_flag = 0;
+
+               }
+
+       }
+
+       if ((file->f_mode & FMODE_WRITE)) {
+               state->wr_ref = 1;
+               audio_reset(os);
+               os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
+               os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
+               os->mapped = 0;
+               init_waitqueue_head(&os->wq);
+       }
+
+       if (file->f_mode & FMODE_READ) {
+               state->rd_ref = 1;
+               audio_reset(is);
+               is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
+               is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
+               is->mapped = 0;
+               init_waitqueue_head(&is->wq);
+       }
+
+       file->private_data = state;
+       err = 0;
+
+      out:
+       up(&state->sem);
+       if (err) {
+               module_put(state->owner);
+               module_put(THIS_MODULE);
+       }
+       FN_OUT(err);
+       return err;
+}
+
+/*********************************************************************************
+ *
+ * audio_release(): Exposed as release function()
+ *
+ *********************************************************************************/
+static int audio_release(struct inode *inode, struct file *file)
+{
+       audio_state_t *state = file->private_data;
+       audio_stream_t *os = state->output_stream;
+       audio_stream_t *is = state->input_stream;
+
+       FN_IN;
+
+       down(&state->sem);
+
+       if (file->f_mode & FMODE_READ) {
+               audio_discard_buf(is);
+               DMA_FREE(is);
+               is->dma_spinref = 0;
+               if (state->need_tx_for_rx) {
+                       os->spin_idle = 0;
+                       if (!state->wr_ref) {
+                               DMA_FREE(os);
+                               os->dma_spinref = 0;
+                       }
+               }
+               state->rd_ref = 0;
+       }
+
+       if (file->f_mode & FMODE_WRITE) {
+               audio_sync(file);
+               audio_discard_buf(os);
+               if (!state->need_tx_for_rx || !state->rd_ref) {
+                       DMA_FREE(os);
+                       os->dma_spinref = 0;
+               }
+               state->wr_ref = 0;
+       }
+
+       if (!AUDIO_ACTIVE(state)) {
+               if (state->hw_shutdown)
+                       state->hw_shutdown(state->data);
+       }
+
+       up(&state->sem);
+
+       module_put(state->owner);
+       module_put(THIS_MODULE);
+
+       FN_OUT(0);
+       return 0;
+}
+
+EXPORT_SYMBOL(audio_register_codec);
+EXPORT_SYMBOL(audio_unregister_codec);
+EXPORT_SYMBOL(audio_get_fops);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("Common audio handling for OMAP processors");
+MODULE_LICENSE("GPL");
diff --git a/sound/oss/omap-audio.h b/sound/oss/omap-audio.h
new file mode 100644 (file)
index 0000000..d3cc11b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * linux/sound/oss/omap-audio.h
+ *
+ * Common audio handling for the OMAP processors
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *  History
+ *  -------
+ *  2004/08/12 Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms
+ *
+ *  2004/04/04 Nishanth menon - Added hooks for power management
+ */
+
+#ifndef __OMAP_AUDIO_H
+#define __OMAP_AUDIO_H
+
+/* Requires dma.h */
+#include <asm/arch/dma.h>
+
+/*
+ * Buffer Management
+ */
+typedef struct {
+       int offset;             /* current offset */
+       char *data;             /* points to actual buffer */
+       dma_addr_t dma_addr;    /* physical buffer address */
+       int dma_ref;            /* DMA refcount */
+       int master;             /* owner for buffer allocation, contain size when true */
+} audio_buf_t;
+
+/*
+ * Structure describing the data stream related information
+ */
+typedef struct {
+       char *id;               /* identification string */
+       audio_buf_t *buffers;   /* pointer to audio buffer structures */
+       u_int usr_head;         /* user fragment index */
+       u_int dma_head;         /* DMA fragment index to go */
+       u_int dma_tail;         /* DMA fragment index to complete */
+       u_int fragsize;         /* fragment i.e. buffer size */
+       u_int nbfrags;          /* nbr of fragments i.e. buffers */
+       u_int pending_frags;    /* Fragments sent to DMA */
+       int dma_dev;            /* device identifier for DMA */
+
+#ifdef OMAP_DMA_CHAINING_SUPPORT
+       lch_chain *dma_chain;
+       dma_regs_t *dma_regs;   /* points to our DMA registers */
+#else
+       char started;           /* to store if the chain was started or not */
+       int dma_q_head;         /* DMA Channel Q Head */
+       int dma_q_tail;         /* DMA Channel Q Tail */
+       char dma_q_count;       /* DMA Channel Q Count */
+       char in_use;            /*  Is this is use? */
+       int *lch;               /*  Chain of channels this stream is linked to */
+#endif
+       int input_or_output;    /* Direction of this data stream */
+       int bytecount;          /* nbr of processed bytes */
+       int fragcount;          /* nbr of fragment transitions */
+       struct completion wfc;  /* wait for "nbfrags" fragment completion */
+       wait_queue_head_t wq;   /* for poll */
+       int dma_spinref;        /* DMA is spinning */
+       unsigned mapped:1;      /* mmap()'ed buffers */
+       unsigned active:1;      /* actually in progress */
+       unsigned stopped:1;     /* might be active but stopped */
+       unsigned spin_idle:1;   /* have DMA spin on zeros when idle */
+       unsigned linked:1;      /* dma channels linked */
+} audio_stream_t;
+
+/*
+ * State structure for one instance
+ */
+typedef struct {
+       struct module *owner;   /* Codec module ID */
+       audio_stream_t *output_stream;
+       audio_stream_t *input_stream;
+       unsigned rd_ref:1;      /* open reference for recording */
+       unsigned wr_ref:1;      /* open reference for playback */
+       unsigned need_tx_for_rx:1; /* if data must be sent while receiving */
+       void *data;
+       void (*hw_init) (void *);
+       void (*hw_shutdown) (void *);
+       int (*client_ioctl) (struct inode *, struct file *, uint, ulong);
+       int (*hw_probe) (void);
+       void (*hw_remove) (void);
+       void (*hw_cleanup) (void);
+       int (*hw_suspend) (void);
+       int (*hw_resume) (void);
+       struct pm_dev *pm_dev;
+       struct semaphore sem;   /* to protect against races in attach() */
+} audio_state_t;
+
+#ifdef AUDIO_PM
+void audio_ldm_suspend(void *data);
+
+void audio_ldm_resume(void *data);
+
+#endif
+
+/* Register a Codec using this function */
+extern int audio_register_codec(audio_state_t * codec_state);
+/* Un-Register a Codec using this function */
+extern int audio_unregister_codec(audio_state_t * codec_state);
+/* Function to provide fops of omap audio driver */
+extern struct file_operations *audio_get_fops(void);
+/* Function to initialize the device info for audio driver */
+extern int audio_dev_init(void);
+/* Function to un-initialize the device info for audio driver */
+void audio_dev_uninit(void);
+
+#endif                         /* End of #ifndef __OMAP_AUDIO_H */